• TopCoder12729 「SRM589Medium」GearsDiv1 二分图最小点覆盖


    问题描述

    (N) 个齿轮每个齿轮有颜色(RGB),有些齿轮之间会咬合,你需要删除尽量少的齿轮并给每种颜色安排方向使得咬合齿轮不同向。问最多保留多少个齿轮。保证不存在两个相同颜色的齿轮咬合。

    submit


    交互输入输出大毒瘤!

    题解

    发现对于 RGB 三种颜色的齿轮,相同颜色不会自己和自己咬合。

    所以可以枚举哪一种颜色的必须保留,剩下来两种咬合就连边,显然是个二分图。


    (mathrm{Code})

    #include<bits/stdc++.h>
    using namespace std;
    
    //#define local
    
    const int INF=0x3f3f3f3f;
    
    int n,S,T;
    int ok[60][60];
    
    int Head[200],to[10007],Next[10007],w[10007],tot=1;
    
    void addedge(int x,int y,int z){
    	to[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=z;
    }
    
    void add(int x,int y,int z){
    	addedge(x,y,z);addedge(y,x,0);
    }
    
    int d[200];
    
    bool bfs(void){
    	memset(d,0,sizeof(d));
    	queue<int>q;q.push(S);d[S]=1;
    	while(q.size()){
    		int x=q.front();q.pop();
    		for(int i=Head[x];i;i=Next[i]){
    			int y=to[i];
    			if(d[y]||!w[i]) continue;
    			d[y]=d[x]+1;q.push(y);
    			if(y==T) return true;
    		}
    	}
    	return false;
    }
    
    int dfs(int x,int flow){
    	if(x==T) return flow;
    	int rest=flow;
    	for(int i=Head[x];i&&rest;i=Next[i]){
    		int y=to[i];
    		if(d[y]!=d[x]+1||!w[i]) continue;
    		int k=dfs(y,min(rest,w[i]));
    		if(!k) d[y]=0;
    		else w[i]-=k,w[i^1]+=k,rest-=k;
    	}
    	return flow-rest;
    }
    
    int Dinic(void){
    	int t,res(0);
    	while(bfs()){
    		while(t=dfs(S,INF)) res+=t; 
    	}
    	return res;
    }
    
    string col,s[50];
    
    void Init(void){
    	cin>>n;cin>>col;
    	for(int i=0;i<n;i++) cin>>s[i];
    }
    
    vector <int> v[4];
    
    void clear(void){
    	tot=1;S=T=0;
    	memset(Head,0,sizeof(Head));
    	memset(Next,0,sizeof(Next));
    }
    
    void debug(void){
    	for(int i=2;i<=tot;i+=2){
    		printf("-- From %d to %d w = %d 
    ",to[i^1],to[i],w[i]);
    	}
    	printf("## S = %d , T = %d
    ",S,T);
    }
    
    void Graph_build(int save){
    	clear();
    	S=2*n+1,T=S+1;
    	int st,nd;
    	if(save==1) st=2,nd=3;
    	else if(save==2) st=1,nd=3;
    	else st=1,nd=2;
    	for(int i=0;i<(int)v[st].size();i++){
    		for(int j=0;j<(int)v[nd].size();j++){
    			int x=v[st][i],y=v[nd][j];
    			if(s[x-1][y-1]=='Y') add(x,y+n,1);
    		}
    	}
    	for(int i=1;i<=n;i++){
    //		add(i,i+n,1);
    		add(S,i,1);add(i+n,T,1);
    	}
    //	debug();
    }
    
    void Preprocess(void){
    	for(int i=0;i<n;i++){
    		int pos;
    		if(col[i]=='R') pos=1;
    		else if(col[i]=='B') pos=2;
    		else pos=3;
    		v[pos].push_back(i+1);
    	}
    }
    
    int Work(void){
    	Preprocess();
    	int maxflow;
    	Graph_build(1);
    	maxflow=Dinic();
    //	printf("** %d
    ",maxflow);
    	Graph_build(2);
    	int tmp=Dinic();
    	maxflow=min(maxflow,tmp);
    //	printf("** %d
    ",tmp);
    	Graph_build(3);
    	tmp=Dinic();
    	maxflow=min(maxflow,tmp);
    //	printf("** %d
    ",tmp);
    	return maxflow;
    }
    
    void Main(void){
    	#ifdef local
    		freopen("hzlbn.in","r",stdin);
    	//	freopen("debug.log","w",stdout);
    	#endif
    	Init();
    	Work();
    }
    
    class GearsDiv1{
    	public:
    		int getmin(string ss,vector<string>md){
    			col=ss;n=ss.size();
    			for(int i=0;i<n;i++) s[i]=md[i];
    			Init();
    			return Work();
    		}
    };
    
  • 相关阅读:
    CF786E ALT
    CF704D Captain America
    [NOI2016]循环之美
    「PKUWC2018」猎人杀
    [HNOI2019]JOJO
    博客已转移
    $20200203$的数学作业
    20200202的数学作业
    NOIp 2016 选课 (DP)
    Luogu P2574 XOR的艺术 (线段树)
  • 原文地址:https://www.cnblogs.com/liubainian/p/12074819.html
Copyright © 2020-2023  润新知