zoukankan      html  css  js  c++  java
  • poj 1815 Friendship【最小割】

    网络流的题总是出各种奇怪的错啊……没写过邻接表版的dinic,然后bfs扫到t点不直接return 1就会TTTTTLE……
    题目中的操作是“去掉人”,很容易想到拆点,套路一般是(s,i')(i,t)(u',v)(v,u),然后关于输出顺序最小方案,可以枚举删点,如果删去一个点后求得最小割比原来的小,那么说明这个点在最小割中,就在图中删掉它并且把最小割标准-1,否则把这个点加回来。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=505,inf=1e9;
    int n,a[N][N],s,t,mx,le[N],ans[N],c[N][N];
    bool del[N];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void build()
    {
    	for(int i=1;i<=n;i++)
    		if(!del[i])
    			c[i][i+n]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			if(a[i][j])
    				c[i+n][j]=inf;
    }
    bool bfs()
    {
    	queue<int>q;
    	memset(le,0,sizeof(le));
    	le[s]=1;
    	q.push(s);
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		for(int v=1;v<=n+n;v++)
    			if(!le[v]&&c[u][v]>0)
    			{
    				le[v]=le[u]+1;
    				if(v==t)
    					return 1;//!!!!!!
    				q.push(v);
    			}
    	}
    	return 0;
    }
    int dfs(int u,int f)
    {
    	if(u==t||!f)
    		return f;
    	int us=0;
    	for(int v=1;v<=n+n&&us<f;v++)
    		if(le[u]+1==le[v]&&c[u][v]>0)
    		{
    			int t=dfs(v,min(c[u][v],f-us));
    			c[u][v]-=t;
    			c[v][u]+=t;
    			us+=t;
    		}
    	if(!us)
    		le[u]=0;
    	return us;
    }
    int dinic()
    {
    	int re=0;
    	while(bfs())
    		re+=dfs(s,inf);//,cout<<re<<endl;
    	return re;
    }
    int main()
    {
    	n=read(),s=read(),t=read();
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			a[i][j]=read();
    	if(a[s][t])
    	{
    		puts("NO ANSWER!");
    		return 0;
    	}
    	s+=n;
    	build();
    	mx=dinic();//printf("%d
    ",mx);
    	for(int i=1;i<=n;i++)
    		if(i!=s-n&&i!=t)
    		{//cout<<i<<endl;
    			del[i]=1;
    			build();
    			if(dinic()<mx)
    			{
    				ans[++ans[0]]=i;
    				mx--;
    				if(!mx)
    					break;
    			}
    			else
    				del[i]=0;
    		}
    	printf("%d
    ",ans[0]);
    	for(int i=1;i<=ans[0];i++)
    		printf("%d ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    .Net Core部署到CentOS
    Docker容器中开始.Net Core之路
    自我总结和学习表单提交的几种方式 (二)
    自我总结和学习表单提交的几种方式 (一)
    Asp.Net MVC下自定义错误页和展示错误页的几种方式
    .Net下发送邮件遇到问题及解决方案
    Asp.Net MVC CodeFirst模式数据库迁移步骤
    利用微软认知服务实现语音识别功能
    Asp.Net MVC路由生成URL过程
    针对于多线程概念的理解
  • 原文地址:https://www.cnblogs.com/lokiii/p/8397402.html
Copyright © 2011-2022 走看看