Optimal Marks SPOJ - OPTM

传送门

一个无向图,每个点有点权,某些点点权确定了,某些点由你来确定,边权为两个点的异或和,要使边权和最小。

这不是一道按位做最小割的大水题么

非常开心地打了,还非常开心地以为有spj,然后非常开心地Wa了

才发现在边权和最小的条件下还要让点权和最小。

这可咋整啊,难不成要费用流。

然后悄悄搜了下题解发现了巧妙的解决方法,把原来建的图中的边权都扩大10000倍,然后在选1的地方边权再悄悄加上1

把它看成10000和1两条边的话,相当于优先考虑大边最小,大边最小的前提下小边最小,即答案。

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<cmath>
 10 #include<set>
 11 #include<map>
 12 #define Formylove return 0
 13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 15 const int M=3500*10,N=550;
 16 typedef long long LL;
 17 typedef double db;
 18 using namespace std;
 19 int n,m,k,qd[N],val[N],ec[M][2];
 20 
 21 template<typename T>void read(T &x)  {
 22     char ch=getchar(); x=0; T f=1;
 23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 24     if(ch=='-') f=-1,ch=getchar();
 25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 26 }
 27 
 28 struct edge {
 29     int u,v,cap,fl,nx;
 30     edge(){}
 31     edge(int u,int v,int cap,int fl,int nx):u(u),v(v),cap(cap),fl(fl),nx(nx){} 
 32 }e[M];
 33 
 34 int ecnt=1,fir[N];
 35 void add(int u,int v,int cap) {
 36     e[++ecnt]=edge(u,v,cap,0,fir[u]); fir[u]=ecnt;
 37     //printf("%d->%d:%d\n",u,v,cap);
 38     e[++ecnt]=edge(v,u,0,0,fir[v]); fir[v]=ecnt;
 39 }
 40 
 41 queue<int>que;
 42 int d[N];
 43 void bfs(int s,int t) {
 44     que.push(t);
 45     For(i,1,n) d[i]=n;
 46     d[t]=0;
 47     while(!que.empty()) {
 48         int x=que.front();
 49         que.pop();
 50         for(int i=fir[x];i;i=e[i].nx) {
 51             int y=e[i].v;
 52             if(d[y]==n&&e[i].cap==0) {
 53                 d[y]=d[x]+1;
 54                 que.push(y); 
 55             }
 56         }
 57     }
 58 }
 59 
 60 #define inf 1e9
 61 int p[N];
 62 int calc(int s,int t) {
 63     int fl=inf;
 64     for(int i=t;i!=s;i=e[p[i]].u)
 65         fl=min(fl,e[p[i]].cap-e[p[i]].fl);
 66     for(int i=t;i!=s;i=e[p[i]].u) 
 67         e[p[i]].fl+=fl,e[p[i]^1].fl-=fl;
 68     return fl;
 69 }
 70 
 71 int c[N],cur[N];
 72 int isap(int s,int t) {
 73     For(i,0,n) c[i]=0;
 74     bfs(s,t);
 75     For(i,1,n) cur[i]=fir[i],c[d[i]]++;
 76     int rs=0;
 77     for(int x=s;d[x]<n;) {
 78         if(x==t) {
 79             rs+=calc(s,t);
 80             x=s;
 81         }
 82         int ok=0;
 83         for(int &i=cur[x];i;i=e[i].nx) if(e[i].cap>e[i].fl&&d[e[i].v]+1==d[x]) {
 84             ok=1; p[x=e[i].v]=i; break;
 85         }
 86         if(!ok) {
 87             int D=n; cur[x]=fir[x];
 88             for(int i=fir[x];i;i=e[i].nx) if(e[i].cap>e[i].fl)
 89                 D=min(D,d[e[i].v]+1);
 90             if(!(--c[d[x]])) break; 
 91             c[d[x]=D]++;
 92             if(x!=s) x=e[p[x]].u;
 93         }
 94     }
 95     return rs;
 96 }
 97 
 98 void init() {
 99     ecnt=1;
100     memset(fir,0,sizeof(fir));
101 }
102 
103 int vis[N];
104 void dfs(int x) {
105     vis[x]=1;
106     for(int i=fir[x];i;i=e[i].nx) if(!vis[e[i].v]&&e[i].cap>e[i].fl)
107         dfs(e[i].v);
108 } 
109 
110 int main() {
111 #ifdef ANS
112     freopen(".in","r",stdin);
113     freopen(".out","w",stdout);
114 #endif
115     int T; read(T);
116     while(T--) {
117         read(n); read(m);
118         For(i,1,m) {
119             read(ec[i][0]);
120             read(ec[i][1]);
121         }
122         read(k);
123         For(i,1,n) val[i]=0,qd[i]=0;
124         For(i,1,k) {
125             int x;
126             read(x); qd[x]=1;
127             read(val[x]);
128         }
129         int s=n+1,t=n+2;
130         For(i,0,30) {
131             init();
132             For(j,1,n) {
133                 if(qd[j]) {
134                     if(val[j]&(1<<i)) {
135                         add(s,j,10000);
136                         add(j,t,inf);
137                     } 
138                     else {
139                         add(s,j,inf);
140                         add(j,t,10000);
141                     }
142                 }
143                 else {
144                     add(s,j,10001);
145                     add(j,t,10000);
146                 }
147             }
148             For(j,1,m) {
149                 int u=ec[j][0],v=ec[j][1];
150                 add(u,v,10000); add(v,u,10000);
151             }
152             n+=2;
153             isap(s,t); 
154             n-=2;
155             memset(vis,0,sizeof(vis));
156             dfs(s);
157             For(j,1,n) if(!vis[j]) val[j]|=(1<<i);
158         }
159         For(i,1,n) printf("%d\n",val[i]);
160         //printf("%d\n",val[n]);
161         /*long long ans=0;
162         for(int i=1;i<=m;i++) {
163             int u=ec[i][0],v=ec[i][1];
164             ans+=(val[u]^val[v]);
165         }
166         printf("%lld\n",ans);*/
167     }
168     Formylove;
169 }
170 /*
171 1
172 6 7
173 1 2
174 2 4
175 1 3
176 2 3
177 4 3
178 1 5
179 5 6
180 4
181 1 5
182 3 1
183 4 7
184 6 2
185 */
View Code

 

posted @ 2018-08-27 19:45  啊宸  阅读(169)  评论(0编辑  收藏  举报