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

  

posted @ 2020-03-19 22:22  EM-LGH  阅读(107)  评论(0编辑  收藏  举报