UVa753 A Plug for UNIX

        题意:有n个插座,m个设备,k种适配器用于转接(每种无限多),接口有自己的类型,只有相同的类型才能接上。问最少有多少设备不能接上插座。

        思路:最大流。建图开始有一点困难了,源->设备->(适配器)->插座->汇这样建。。程序复杂了不是那么好调,坑了好久。。其实只要建图建好了,剩下的不是问题。


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
#define INF 1000000000
using namespace std;

int t,n,m,k;
string nn[110];
string mm[110];
string kk1[110];
string kk2[110];
int map[310][310];

int main(){
	cin>>t;
	while(t--){
		memset(map,0,sizeof(map));
		cin>>n;//插座 
		for(int i=1;i<=n;i++){
			cin>>nn[i];
		}
		cin>>m;//设备 
		string dev;
		for(int i=1;i<=m;i++){
			cin>>dev>>mm[i];
		}
		cin>>k;//适配器 
		for(int i=1;i<=k;i++){
			cin>>kk1[i]>>kk2[i];
		}
		//源到设备 
		for(int i=1;i<=m;i++){
			map[0][n+i]=1;
		}
		//设备到插座
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(nn[i]==mm[j]){
					map[n+j][i]=1;
				}
			}
		}
		//插座到汇
		for(int i=1;i<=n;i++){
			map[i][n+m+k+1]=1;
		} 
		//设备到适配器 
		for(int i=1;i<=m;i++){
			for(int j=1;j<=k;j++){
				if(mm[i]==kk1[j]){
					map[n+i][n+m+j]=1;
				}
			}
		}
		//适配器之间
		for(int i=1;i<=k;i++){
			for(int j=1;j<=k;j++){
				if(kk1[i]==kk2[j]){
					map[n+m+j][n+m+i]=INF;
				}
			}
		} 
		//适配器到插座
		for(int i=1;i<=n;i++){
			for(int j=1;j<=k;j++){
				if(nn[i]==kk2[j]){
					map[n+m+j][i]=INF;
				}
			}
		} 

		//最大流
		int ans=0;
		int pre[310];
		int a[310];
		int flow[310][310];
		memset(flow,0,sizeof(flow));
		while(true){
			memset(a,0,sizeof(a));
			queue<int> que;que.push(0);
			while(!que.empty()){
				int cur=que.front();que.pop();
				for(int i=0;i<=(n+m+k+1);i++){
					if( !a[i]&&(map[cur][i]>flow[cur][i]) ){
						a[i]=1;
						pre[i]=cur;
						que.push(i);
						if(i==(n+m+k+1))break;
					}
				}
			}
			if(!a[n+m+k+1])break;
			ans++; 
			for(int i=(n+m+k+1);i!=0;i=pre[i]){
				flow[pre[i]][i]++;
				flow[i][pre[i]]--;
			}
		}
		
		cout<<m-ans<<endl;
		if(t)cout<<endl; 
		
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值