1143: [CTSC2008]祭祀river
阿新 • • 發佈:2018-09-18
ble mic () status print ros span iostream 祭祀river Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 4018 Solved: 2048
[Submit][Status][Discuss]
須非常慎重。準確地說,Y族人認為,如果水流可以從一個祭祀點流到另外一個祭祀點,那麽祭祀就會失去它神聖
的意義。族長希望在保持祭祀神聖性的基礎上,選擇盡可能多的祭祀的地點。
1 2
3 4
3 2
4 2
【樣例說明】
在樣例給出的水系中,不存在一種方法能夠選擇三個或者三個以上的祭祀點。包含兩個祭祀點的測試點的方案有兩種:
選擇岔口1與岔口3(如樣例輸出第二行),選擇岔口1與岔口4。
水流可以從任意岔口流至岔口2。如果在岔口2建立祭祀點,那麽任意其他岔口都不能建立祭祀點
但是在最優的一種祭祀點的選取方案中我們可以建立兩個祭祀點,所以岔口2不能建立祭祀點。對於其他岔口
至少存在一個最優方案選擇該岔口為祭祀點,所以輸出為1011。 Dilworth定理:偏序集能劃分成的最少的全序集的個數與最大反鏈的元素個數相等。 證明:http://www.cnblogs.com/itlqs/p/6636222.html
在有向無環圖中,有如下的一些定義和性質:
鏈:一條鏈是一些點的集合,鏈上任意兩個點x, y,滿足要麽 x 能到達 y ,要麽 y 能到達 x 。
反鏈:一條反鏈是一些點的集合,鏈上任意兩個點x, y,滿足 x 不能到達 y,且 y 也不能到達 x。
一個定理:最長反鏈長度 = 最小鏈覆蓋(用最少的鏈覆蓋所有頂點)
對偶定理:最長鏈長度 = 最小反鏈覆蓋
題目問題可以轉化為求最長反鏈的長度,而最長反鏈可以由二分圖匹配來求
首先用floyd算法判斷聯通性,建立連通圖
接下來建立二分圖,左邊n個點,右邊n個點,按照河道連接
跑一遍二分圖匹配
ans=n-二分圖最大匹配
Submit: 4018 Solved: 2048
[Submit][Status][Discuss]
Description
在遙遠的東方,有一個神秘的民族,自稱Y族。他們世代居住在水面上,奉龍王為神。每逢重大慶典, Y族都 會在水面上舉辦盛大的祭祀活動。我們可以把Y族居住地水系看成一個由岔口和河道組成的網絡。每條河道連接著 兩個岔口,並且水在河道內按照一個固定的方向流動。顯然,水系中不會有環流(下圖描述一個環流的例子)。由於人數眾多的原因,Y族的祭祀活動會在多個岔口上同時舉行。出於對龍王的尊重,這些祭祀地點的選擇必
Input
第一行包含兩個用空格隔開的整數N、M,分別表示岔口和河道的數目,岔口從1到N編號。 接下來M行,每行包含兩個用空格隔開的整數u、v, 描述一條連接岔口u和岔口v的河道,水流方向為自u向v。 N≤100M≤1000Output
第一行包含一個整數K,表示最多能選取的祭祀點的個數。
Sample Input
4 41 2
3 4
4 2
Sample Output
2【樣例說明】
在樣例給出的水系中,不存在一種方法能夠選擇三個或者三個以上的祭祀點。包含兩個祭祀點的測試點的方案有兩種:
選擇岔口1與岔口3(如樣例輸出第二行),選擇岔口1與岔口4。
水流可以從任意岔口流至岔口2。如果在岔口2建立祭祀點,那麽任意其他岔口都不能建立祭祀點
但是在最優的一種祭祀點的選取方案中我們可以建立兩個祭祀點,所以岔口2不能建立祭祀點。對於其他岔口
至少存在一個最優方案選擇該岔口為祭祀點,所以輸出為1011。 Dilworth定理:偏序集能劃分成的最少的全序集的個數與最大反鏈的元素個數相等。 證明:http://www.cnblogs.com/itlqs/p/6636222.html
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 6 const int MAXN=2000; 7 int n,m,ans; 8 int match[MAXN]; 9 bool map[MAXN][MAXN],vis[MAXN]; 10 11 bool find(int x) 12 { 13 for(int i=1;i<=n;i++) 14 if(map[x][i]&&!vis[i]) 15 { 16 vis[i]=true; 17 if(match[i]==0||find(match[i])) 18 { 19 match[i]=x; 20 return true; 21 } 22 } 23 return false; 24 } 25 26 int main() 27 { 28 scanf("%d%d",&n,&m); 29 for(int i=1;i<=m;i++) 30 { 31 int x,y; 32 scanf("%d%d",&x,&y); 33 map[x][y]=1; 34 } 35 for(int i=1;i<=n;i++) 36 for(int j=1;j<=n;j++) 37 for(int k=1;k<=n;k++) 38 if(map[i][k]&&map[k][j]) map[i][j]=1; 39 for(int i=1;i<=n;i++) 40 { 41 memset(vis,0,sizeof(vis)); 42 if(find(i)) ans++; 43 } 44 printf("%d\n",n-ans); 45 return 0; 46 }
1143: [CTSC2008]祭祀river