• 洛谷P2057 [SHOI2007]善意的投票 题解


    题目链接:

    https://www.luogu.org/problemnew/show/P2057

    分析:

    由0和1的选择我们直觉的想到0与S一堆,1与T一堆。

    但是发现,刚开始的主意并不一定是最终的结果。

    于是用源点S表示最终选择0的集合。

    汇点T表示最终选择1的集合。

    如果一个人P选择了0,那么S>PS->P连一条流量为1的边,然后P>TP->T连一条流量为0的边。

    反之如果P选择了1,那么S>PS->P连一条流量为0的边,然后P>TP->T连一条流量为1的边。

    最后把所有朋友对之间连流量为1的双向边(关系相互)

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<queue>
    #define inf 0x7fffffff
    using namespace std;
    int s,t,ans;
    int d[505];
    struct edge
    {
    	int to,val,rev;
    	edge(int _to,int _val,int _rev)
    	{
    		to=_to;
    		val=_val;
    		rev=_rev;
    	}
    };
    vector<edge>e[505];
    void add(int x,int y,int w)
    {
    	e[x].push_back(edge(y,w,e[y].size()));
    	e[y].push_back(edge(x,0,e[x].size()-1));
    }
    bool bfs()
    {
    	queue<int>q; 
    	memset(d,-1,sizeof(d));
    	d[s]=0;
    	q.push(s);
    	while(!q.empty())
    	{
    		int x=q.front();q.pop();
    		for(int i=0;i<e[x].size();i++)
    		{
    			int y=e[x][i].to;
    			if(d[y]==-1&&e[x][i].val)
    			{
    				q.push(y);
    				d[y]=d[x]+1;
    			}
    		}
    	} 
    	if(d[t]==-1)return 0;
    	return 1;
    }
    int dfs(int x,int low) 
    {
        if(x==t || low==0)
            return low;
        int totflow=0; 
        for(int i=0;i<e[x].size();i++)
        {
            int y=e[x][i].to;
            int rev=e[x][i].rev;
            if(d[y]==d[x]+1 && e[x][i].val)
            {
                int a=dfs(y,min(low,e[x][i].val)); 
                e[x][i].val-=a;
                e[y][rev].val+=a;
                low-=a;
                totflow+=a;
                if(low==0) 
                    return totflow;
            }
        }
        if(low!=0) 
            d[x]=-1;
        return totflow;
    }
    
    void dinic()
    {
    	while(bfs())
    	{
    		//printf("%d
    ",ans); 
    		ans+=dfs(s,inf); 
    	}
    }
    int main()
    {
    	int n,m,x,y,o;
    	scanf("%d%d",&n,&m);
    	s=0;t=500;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&o);
    		if(o==0)
    		{
    			add(s,i,1);//add(i,t,0);
    		}
    		else
    		{
    			//add(s,i,0);
    			add(i,t,1);
    		}
    	}
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		add(x,y,1);add(y,x,1);
    	}
    	dinic();
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    [转]C#中抽象类和接口的区别
    [转]OO设计原则总结
    [转]MVC3快速搭建Web应用(三)实例篇
    原生内存(堆外内存)
    使用SAX解析XML实例根据属性查找
    Cannot forward after response has been committed问题解决及分析
    dubbo服务化实施整理
    bean:write 标签不能显示出 换行符的解决方案
    Dubbo原理解析监控
    thread之1:java与线程
  • 原文地址:https://www.cnblogs.com/ShineEternal/p/10834224.html
Copyright © 2020-2023  润新知