zoukankan      html  css  js  c++  java
  • SP839 OPTM

    最小割.  

    显然按位拆分,然后对于有矛盾的连流量为 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
    ",answer[i]);   
    }
    int main() 
    {
        //  setIO("input");  
        int T;   
        scanf("%d",&T);   
        while(T--)  
            solve();   
        return 0; 
    }
    

      

  • 相关阅读:
    Android标题栏最右边添加按钮
    Activity标题栏添加返回按钮
    【Android】解决Android横竖屏切换数据丢失问题的方法
    Android热更新,到底是更新啥?
    vm ware 虚拟WIN10 时,chrome ,cent browser 显示异常,花屏
    动态生成的 select option 无法选中,设置值
    安装sql 2012 时遇到“需要更新的以前的 Visual Studio 2010 实例。”规则失败。
    C#.NET 简单使用log4net
    10位,13位时间戳转为C#格式时间
    C# .NET Unix 时间戳
  • 原文地址:https://www.cnblogs.com/guangheli/p/12527665.html
Copyright © 2011-2022 走看看