1. 程式人生 > >codeforces 1043 E. Train Hard, Win Easy

codeforces 1043 E. Train Hard, Win Easy

題目
傳送門

題意:
有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;
}