1. 程式人生 > >JZYZOJ1349 SPOJ839 星屑幻想 xor 網絡流 最大流

JZYZOJ1349 SPOJ839 星屑幻想 xor 網絡流 最大流

|| http 二進制 求解 sin pen 代碼 網絡流 const

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

JZYZOJ1349 SPOJ839 星屑幻想 xor 網絡流 最大流