hdu 6166

来源:互联网 发布:雷神笔记本怎么样知乎 编辑:程序博客网 时间:2024/06/16 16:03

题目链接:点击打开链接


题解思路:把所有数转化为二进制那么肯定保证了至少有一位是不同的,10^5小于20位,那么枚举每一位将这位是0的加入一个集合1的加入另外一个集合,跑20次SPFA就行了,那就保证任意两对都会被分到不同集合过。


代码:

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<math.h>#include<queue>#define inf 0x3f3f3f3fusing namespace std;typedef long long ll;const int mx = 1e5+10;int n,m,head[mx],q,num[mx],tot;struct node{    int y,nxt;    int v;}Edge[mx<<1];bool vis[mx],vic[mx];ll dis[mx];queue<int>que;void AddEdge(int x,int y,int v){    Edge[tot].y = y;    Edge[tot].v = v;    Edge[tot].nxt = head[x];    head[x] = tot++;}ll spfa(){    ll ans = 1e15;    while(!que.empty()){        int po = que.front();        que.pop();        vis[po] = 0;        for(int i=head[po];i!=-1;i=Edge[i].nxt){            int son = Edge[i].y;            if(min(ans,dis[son])>dis[po]+Edge[i].v){                dis[son] = dis[po] + Edge[i].v;                if(vic[son]) ans = min(ans,dis[son]);                if(!vis[son]){                    vis[son] = 1;                    que.push(son);                }            }        }    }    return ans;}void init(){    memset(vic,0,sizeof(vic));    for(int i=1;i<=n;i++) dis[i] = 1e15;}ll solve(){    ll ans = 1e15;    for(int i=0;i<20;i++){        init();        for(int j=1;j<=q;j++){            if(num[j]&(1<<i)){                que.push(num[j]);                dis[num[j]] = 0;                vis[num[j]] = 1;            }            else vic[num[j]] = 1;        }        ans = min(ans,spfa());        init();        for(int j=1;j<=q;j++){            if(num[j]&(1<<i)) vic[num[j]] = 1;            else{                que.push(num[j]);                dis[num[j]] = 0;                vis[num[j]] = 1;            }        }        ans = min(ans,spfa());    }    return ans;}int main(){    int t,cas = 1;    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        memset(head,-1,sizeof(head));        tot = 0;        int a,b,c;        while(m--){            scanf("%d%d%d",&a,&b,&c);            AddEdge(a,b,c);        }        scanf("%d",&q);        for(int i=1;i<=q;i++) scanf("%d",num+i);        printf("Case #%d: %lld\n",cas++,solve());    }    return 0;}