JZYZOJ1349 SPOJ839 星屑幻想 xor 网络流 最大流

http://172.20.6.3/Problem_Show.asp?id=1349

调了两个小时发现数组开小了[doge]。
题意:给出几个点,有的点的权值确定,连接两点的边的权值为两点值的异或和,求所有边权值的和最小的点权值的方案(若有多种方案,输出点的权值和最小的方案)。

不严谨的方案证明(严谨的方案应该和最小割有关):首先,当每个未知权值的点只与几个已知权值的点相连时,显然这个点二进制的每一位都取这些相连的权值中此位最多的,以争取到更多的此位为0。
因为要求输出点的权值也尽量小,所以当某一位相连的0和1相等时,这一位取0。

这种方案可以扩展到那些连接有未知权值点的未知权值点,此时问题就可以按位用网络流求解出最小方案的二进制每一位从而求出数。
计算到某一位时,
s向所有确定权值的该位为1的点连一条权值为无穷的有向边,
所有确定权值的该位为0的点向t连一条权值为无穷的有向边,
题目中相连的边都为权值为1的无向边,
然后从s向t网络流,结束后连1多的点到s有 所有边的权值都大于0的一条路 ,否则没有,据此求出该位。

代码

  1 #include<iostream>  
  2 #include<cstdio>  
  3 #include<cstring>  
  4 #include<algorithm>  
  5 #include<cmath>
  6 #include<queue>
  7 using namespace std;
  8 const int maxn=510;
  9 const long long inf=100000000000000000LL;
 10 long long n,m;
 11 long long val[maxn];
 12 struct cu{
 13     long long x,y;
 14 }a[maxn*20];
 15 struct nod{
 16     long long y,v,next;
 17 }e[maxn*20];
 18 long long head[maxn]={},tot=0;
 19 bool vis[maxn]={};
 20 long long ans[maxn]={};
 21 long long dep[maxn]={};
 22 void insert(long long x,long long y,long long v1,long long v2){
 23     e[++tot].y=y;e[tot].next=head[x];e[tot].v=v1;head[x]=tot;
 24     e[++tot].y=x;e[tot].next=head[y];e[tot].v=v2;head[y]=tot;
 25 }
 26 bool bfs(long long s,long long t){
 27     queue<long long>q;while(!q.empty())q.pop();
 28     memset(dep,0,sizeof(dep));
 29     q.push(s);q.push(s);dep[s]=1;long long x,y,v;
 30     while(!q.empty()){
 31         x=q.front();q.pop();
 32         for(int i=head[x];i;i=e[i].next){
 33             y=e[i].y;v=e[i].v;
 34             if(v>0&&!dep[y]){
 35                 dep[y]=dep[x]+1;q.push(y);
 36             }
 37         }
 38     }
 39     return dep[t];
 40 }
 41 long long dfs(long long x,long long t,long long mi){
 42     if(x==t||mi==0)return mi;
 43     long long y,v,tsn=0,z;
 44     for(int i=head[x];i;i=e[i].next){
 45         y=e[i].y;v=e[i].v;
 46         if(v>0&&dep[y]==dep[x]+1){
 47             z=dfs(y,t,min(mi-tsn,v));
 48             e[i].v-=z;e[i^1].v+=z;
 49             tsn+=z;
 50             if(tsn==mi)return tsn;
 51         }
 52     }
 53     return tsn;
 54 }
 55 void dinic(long long s,long long t){
 56     while(bfs(s,t)){
 57         dfs(s,t,inf);
 58     }
 59 }
 60 void dra(long long x,long long v){
 61     long long  y;vis[x]=1;ans[x]+=v;
 62     for(int i=head[x];i;i=e[i].next){
 63         y=e[i].y;
 64         if(e[i].v>0&&!vis[y]){
 65             dra(y,v);
 66         }
 67     }
 68 }
 69 void doit(){
 70     long long v=1,s=n+1,t=n+2;
 71     for(;;){
 72         memset(vis,0,sizeof(vis));
 73         memset(head,0,sizeof(head));tot=1;
 74         for(int i=1;i<=m;i++){
 75             insert(a[i].x,a[i].y,1,1);
 76         }int f=0;
 77         for(int i=1;i<=n;i++){
 78             if(val[i]!=-1){
 79                 if(val[i]>0)f=1;
 80                 if(val[i]%2)insert(s,i,inf,0);
 81                 else insert(i,t,inf,0);
 82                 val[i]/=2;
 83             }
 84         }
 85         if(!f)break;
 86         dinic(s,t);
 87         dra(s,v);
 88         v*=2;
 89     }
 90     for(int i=1;i<=n;i++){
 91         printf("%I64d\n",ans[i]);
 92     }
 93 }
 94 int main(){
 95     //freopen("wtf.in","r",stdin);
 96     scanf("%I64d%I64d",&n,&m);
 97     for(int i=1;i<=m;i++){
 98         scanf("%I64d%I64d",&a[i].x,&a[i].y);
 99     }long long k,x,y;scanf("%I64d",&k);memset(val,-1,sizeof(val));
100     for(int i=1;i<=k;i++){
101         scanf("%I64d%I64d",&x,&y);val[x]=y;
102     }doit();
103     return 0;
104 }
View Code

 

posted @ 2017-11-05 18:30  鲸头鹳  阅读(242)  评论(0编辑  收藏  举报