1143: [CTSC2008]祭祀river
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2991 Solved: 1528
[Submit][Status][Discuss]
Description
Input
Output
第一行包含一個整數K,表示最多能選取的祭祀點的個數。
Sample Input
1 2
3 4
3 2
4 2
Sample Output
【樣例說明】
在樣例給出的水系中,不存在一種方法能夠選擇三個或者三個以上的祭祀點。包含兩個祭祀點的測試點的方案有兩種:
選擇岔口1與岔口3(如樣例輸出第二行),選擇岔口1與岔口4。
水流可以從任意岔口流至岔口2。如果在岔口2建立祭祀點,那麼任意其他岔口都不能建立祭祀點
但是在最優的一種祭祀點的選取方案中我們可以建立兩個祭祀點,所以岔口2不能建立祭祀點。對於其他岔口
至少存在一個最優方案選擇該岔口爲祭祀點,所以輸出爲1011。
HINT
Source
code
二分圖最大匹配水水,被迫複習圖論。
#include<bits/stdc++.h>
using namespace std;
inline void read(int &res){
static char ch;int flag=1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
const int N = 1000100;
int n,tot,m,vis[N],tim,ans,num[N];
int mp[200][200];
bool find(int x){
for(register int i=1;i<=n;++i){
if(mp[x][i]&&vis[i]!=tim){
vis[i]=tim;
if(!num[i]||find(num[i])){
num[i]=x;
return 1;
}
}
}
return 0;
}
int main(){
read(n);read(m);
for(register int x,y,i=1;i<=m;i++){
read(x),read(y);
mp[x][y]=1;
}
for(register int i,j,k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
mp[i][j]|=mp[i][k]&mp[k][j];
for(register int i=1;i<=n;i++){
++tim;
if(find(i))ans++;
}
printf("%d\n",n-ans);
return 0;
}