题目大意:
有两台机器A和B以及K个需要运行的任务。A机器有N种不同的模式,B机器有M种不同的模式,而每个任务都恰好在一台机器上运行。
如果它在机器A上运行,则机器A需要设置为模式xi,如果它在机器B上运行,则机器A需要设置为模式yi。
每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次。请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。
题解:
把机器A的N种模式作为二分图的左部,机器B的M种模式作为二分图的右部,如果某个任务可以使用机器A的模式xi也可以使用机器B的模式yi完成,则连接xi,yi。
由于要使得机器重启的次数最少而又要完成所有的任务,题目转化为从这N+M个点中取出最少数量的点覆盖所有的边。
又根据二分图的性质:最小点覆盖=最大匹配数,可以使用匈牙利算法求出答案
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<stack> 6 #include<queue> 7 #include<cstring> 8 #define pau putchar(' ') 9 #define ent putchar(' ') 10 #define mse(a,b) memset(a,b,sizeof(a)) 11 #define ren(x) for(ted*e=fch[x];e;e=e->nxt) 12 #define rep(i,s,t) for(int i=s,__=t;i<=__;i++) 13 #define dwn(i,s,t) for(int i=s,__=t;i>=__;i--) 14 using namespace std; 15 const int maxn=200+10,maxm=40000+10; 16 int lnk[maxn];bool vis[maxn]; 17 struct ted{int x,y;ted*nxt;}adj[maxm],*fch[maxn],*ms=adj; 18 void add(int x,int y){*ms=(ted){x,y,fch[x]};fch[x]=ms++;return;}int n,m,k; 19 bool match(int x){ 20 ren(x){int v=e->y;if(!vis[v]){vis[v]=true; 21 if(!lnk[v]||match(lnk[v])){lnk[v]=x;return true;} 22 } 23 }return false; 24 } 25 int hungary(){ 26 mse(lnk,false);int ans=0;rep(i,1,n){mse(vis,false);if(match(i))ans++;}return ans; 27 } 28 inline int read(){ 29 int x=0;bool sig=true;char ch=getchar(); 30 for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=false; 31 for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';return sig?x:-x; 32 } 33 inline void write(int x){ 34 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 35 int len=0;static int buf[20];while(x)buf[len++]=x%10,x/=10; 36 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 37 } 38 int main(){ 39 while(true){ 40 n=read();if(!n)break; 41 mse(fch,NULL);ms=adj; 42 m=read();k=read();int x,y; 43 rep(i,1,k){ 44 read();x=read();y=read();if(x&&y)add(x,y); 45 }write(hungary());ent; 46 } 47 return 0; 48 }