• POJ 2125 Destroying The Graph 二分图 最小点权覆盖


    POJ2125 

    题意简述:给定一个有向图,要通过某些操作删除所有的边,每一次操作可以选择任意一个节点删除由其出发的所有边或者通向它的所有边,两个方向有不同的权值。问最小权值和的解决方案,要输出操作。

    乍一看是要用点去覆盖边,联想到二分图的最小点权覆盖,通过拆点,我们可以得到二分图。每个点都拆成两个点,一个作为入点,另一个作为出点。于是我们构建了一个标准的二分图最小点权覆盖的模型

    解决二分图最小点权覆盖的的算法并不复杂,创造一个源点和汇点,源点到左边的点连边,容量为对应点的权值,同理右边的点向汇点连边。然后运行最大流,就可以得到最小权值和。

    下一步就是输出解决方案,也就是求最小割边集。在运行完最大流的残量网络中由源点出发BFS所有可以到达的点构成了源点集。对于剩下的边,如果满流且一个端点属于源点集而另一个端点不属于,则这条边属于最小割。

    代码实现比较简单:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<queue>
    using namespace std;
    const int maxn=110*2,maxm=5000,s=0,INF=9999999;
    int n,m,t,cap[maxn][maxn],flow[maxn][maxn],w[maxn];
    
    int augment(int fa[])
    {
     int d[maxn];
     memset(d,0,sizeof(d));
     d[s]=INF;
     queue<int>q;q.push(s);
     while(!q.empty())
     	{
     	 int u=q.front();q.pop();
     	 for(int i=s;i<=t;i++)
     	 	{
     	 	 if((d[i]!=0)||(cap[u][i]<=flow[u][i]))continue;
     	 	 d[i]=min(d[u],cap[u][i]-flow[u][i]);
     	 	 q.push(i);
     	 	 fa[i]=u;
     	 	 if(i==t)return d[t];
    		}
    	} 
     return d[t];
    }
    
    int  maxflow()
    { 
      int fa[maxn];
      int ans=0;
      
      while(true)
      	{
      	 int nflow=augment(fa);
      	 if(nflow==0)return ans;
      	 ans+=nflow;
      	 for(int i=t;i!=s;i=fa[i])
      	 	{
      	 	 flow[fa[i]][i]+=nflow;
      	 	 flow[i][fa[i]]-=nflow;
    		}
    	}
    }
    vector<int> mincut()
    {
     bool vis[maxn];
     memset(vis,0,sizeof(vis));
     vis[s]=true;
     queue<int>q;
     q.push(s);
     while(!q.empty())
     	{
     	 int u=q.front();q.pop();
     	 for(int i=s;i<=t;i++)
     	 	{
     	 	 if((vis[i])||(cap[u][i]<=flow[u][i]))continue;
     	 	 vis[i]=true;
     	 	 q.push(i);
    		}
    	}
     vector<int>ans;
     for(int i=s;i<=t;i++)
     	if(vis[i])for(int j=s;j<=t;j++)
     				if(!vis[j]&&cap[i][j]==flow[i][j]&&cap[i][j]>0)
     					{
     					 if(i==s){ans.push_back(j);}
     					 if(j==t){ans.push_back(i);}
    					}
     return ans;
    }
    
    void print(vector<int> vec)
    {
     cout<<vec.size()<<endl;
     for(int i=0;i<vec.size();i++)
     	{
     		if(vec[i]<=n)cout<<vec[i]<<" -"<<endl;
     			else cout<<vec[i]-n<<" +"<<endl;
    	}
    }
    int main()
    {
     ios::sync_with_stdio(false);
     memset(cap,0,sizeof(cap));memset(flow,0,sizeof(flow));
     cin>>n>>m;
     t=n*2+1;
     for(int i=1;i<=n*2;i++)
     	cin>>w[i];
     for(int i=0;i<m;i++)
     	{
     	 int a,b;
     	 cin>>a>>b;
     	 cap[a][b+n]=INF;
    	}
     for(int i=1;i<=n;i++)
     	{
     	 cap[s][i]=w[i+n];
     	 cap[i+n][t]=w[i];
    	}
     cout<<maxflow()<<endl;
     print( mincut() );
     return 0;
    }
    

      东北欧赛区的题目还是很给力的

  • 相关阅读:
    win7 powershell版本过低问题
    使用VirtualBox + Vagrant打造统一的开发环境
    Windows中查看PowerShell版本和virbox版本,vagrant 版本
    Please upgrade the installed version of powershell to the minimum required version and run the command again.
    PHP Laravel系列之环境搭建( VirtualBox+Vagrant+Homestead+系列网址)
    PHP实现redis限制单ip、单用户的访问次数功能
    错误信息:FATAL: No bootable medium found! System halted.
    VirtualBox下安装ubuntu server 16.04
    我的arcgis培训照片13
    我的arcgis培训照片12
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6423468.html
Copyright © 2020-2023  润新知