题目
传送门
题意:
有n个人,m个排斥关系,有一个竞赛,有两道题目,给出n个人做两道题的做题速度,然后求分别这n个人做题时间累积的最小值。每个人只能做一道题,下一个题目必须他的同伴来做。有排斥关系的两个人不能相互组队。
思路:
设i的做题时间分别为xi,yi,j的做题时间分别为xj,yj。
若让i做第一题,j做第二题,则必须满足以下不等式:
xi+yj<xj+yi; 则 xi-yi<xj-yj, 只要是满足xj-yj>xi-yi的形式一定是i做第一题。
同理,i做第二题,j做第一题也是一样的做法。
然后再减去相互排斥的人就可以了。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=3*1e5+5;
int n,m;
struct score
{
ll a,b,t;
int id;
};
score a[maxn],b[maxn];
int loc[maxn];
ll suma[maxn],sumb[maxn];
ll Min[maxn];
vector<int>v[maxn];
int compare (score a,score b)
{
return a.t<b.t;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%lld%lld",&a[i].a,&a[i].b);
a[i].t=a[i].a-a[i].b;
a[i].id=i;
b[i]=a[i];
}
sort (a+1,a+n+1,compare);
suma[0]=0; sumb[0]=0;
for (int i=1;i<=n;i++)
{
suma[i]=suma[i-1]+a[i].a;
sumb[i]=sumb[i-1]+a[i].b;
}
for (int i=1;i<=n;i++)
{
ll temp1=0,temp2=0,temp=0;
temp1=sumb[n]-sumb[i]+(n-i)*a[i].a;
temp2=suma[i-1]+(i-1)*a[i].b;
Min[a[i].id]=temp1+temp2;
}
for (int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ll t=min(b[x].a+b[y].b,b[x].b+b[y].a);
Min[x]-=t;
Min[y]-=t;
}
for (int i=1;i<=n;i++)
{
printf("%lld%c",Min[i],i==n?'\n':' ');
}
return 0;
}