SP839 OPTM - Optimal Marks 最小割
最小割.
显然按位拆分,然后对于有矛盾的连流量为 1 的边,代表如果然不同颜色需要花费 1 的代价.
跑一个最大流即可.
code:
#include <bits/stdc++.h> #define N 560 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; const ll inf=2000000001; int answer[N]; namespace net { struct Edge { int u,v; ll c; Edge(int u=0,int v=0,ll c=0):u(u),v(v),c(c){} }; queue<int>q; vector<Edge>edges; vector<int>G[N]; int vv[N],vis[N],d[N],bo[N],s,t; void add(int u,int v,ll c) { edges.push_back(Edge(u,v,c)); edges.push_back(Edge(v,u,0)); int o=edges.size(); G[u].push_back(o-2); G[v].push_back(o-1); } ll dfs(int x,ll cur) { if(x==t) return cur; ll an=0,flow=0; for(int i=vv[x];i<G[x].size();++i,++vv[x]) { Edge e=edges[G[x][i]]; if(e.c>0&&d[e.v]==d[x]+1) { an=dfs(e.v,min(cur,e.c)); if(an) { cur-=an; flow+=an; edges[G[x][i]].c-=an; edges[G[x][i]^1].c+=an; if(!cur) break; } } } return flow; } int bfs() { memset(vis,0,sizeof(vis)); d[s]=0; vis[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=0;i<G[u].size();++i) { if(edges[G[u][i]].c>0) { int v=edges[G[u][i]].v; if(!vis[v]) { vis[v]=1; d[v]=d[u]+1; q.push(v); } } } } return vis[t]; } ll maxflow() { ll re=0; while(bfs()) { memset(vv,0,sizeof(vv)); re+=(ll)dfs(s,inf); } return re; } void clr() { memset(d,0,sizeof(d)); memset(bo,0,sizeof(bo)); memset(vv,0,sizeof(vv)); memset(vis,0,sizeof(vis)); edges.clear(); for(int i=0;i<N;++i) G[i].clear(); } void dfs(int x,int ma) { if(bo[x]) return; bo[x]=1; answer[x]+=ma; for(int i=0;i<G[x].size();++i) { Edge e=edges[G[x][i]]; if(e.c>0) dfs(e.v,ma); } } }; int gu[3005],gv[3005]; int val[N],a[N]; void solve() { int n,m,s,t; scanf("%d%d",&n,&m); s=0,t=n+1; memset(answer,0,sizeof(answer)); for(int i=1;i<=m;++i) scanf("%d%d",&gu[i],&gv[i]); int k; scanf("%d",&k); for(int i=1;i<=k;++i) { scanf("%d",&a[i]); scanf("%d",&val[i]); } for(int i=0;i<31;++i) { int cu=(1<<i); net::clr(); net::s=s,net::t=t; for(int j=1;j<=k;++j) { if(val[j]&cu) net::add(s,a[j],inf); else net::add(a[j],t,inf); } for(int j=1;j<=m;++j) { int x=gu[j],y=gv[j]; net::add(x,y,1); net::add(y,x,1); } net::maxflow(); net::dfs(s,cu); } for(int i=1;i<=n;++i) printf("%d\n",answer[i]); } int main() { // setIO("input"); int T; scanf("%d",&T); while(T--) solve(); return 0; }