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;
}

浙公网安备 33010602011771号