URAL 1721 Two Sides of the Same Coin(二分图匹配,输出匹配对象)
生活随笔
收集整理的這篇文章主要介紹了
URAL 1721 Two Sides of the Same Coin(二分图匹配,输出匹配对象)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:給出n個人的信息,名字、特征、排名。
? ? ? ?在排名相差2的前提下,特征為testdata可以與特征為statements的組隊,特征為anything可以任何一人組隊;
? ? ? ?求最多匹配對數,并將每隊名字輸出;
思路:將排名%4,結果小于2的一組,大于等于2的一組,則同一組中不會匹配,以此構建二分圖;二分圖匹配;
? ? ? ? 匈牙利算法的思想是:
? ? ? ? ? ? 左點集與右點集匹配:
? ? ? ? ? ? 1)有匹配的先匹配;
? ? ? ? ? ? 2)后來匹配的如果與前面的匹配沖突,前面的匹配重新匹配,如果匹配成功了,則加上新匹配;否則新匹配不成立;
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int link[5050],vis[5050]; int n,m,h; int match[5055][5050],rk[5050]; char name[5050][505],str[505][5050]; int left[5050],right[5050],sta[5050]; int dfs(int x) {int i;for(i=1;i<=m;i++){if(!vis[i]&&match[x][i]){vis[i]=1;if(link[i]==-1||dfs(link[i])){link[i]=x;return 1;}}}return 0; } int hungary() {int sum=0,j;memset(link,-1,sizeof(link));for(j=1;j<=h;j++){memset(vis,0,sizeof(vis));if(dfs(j)) sum++;}return sum; } int main() {int i,j,k,res;while(scanf("%d",&n)!=EOF){for(i=1;i<=n;i++){scanf("%s%s%d",name[i],str[i],&rk[i]);if(strcmp(str[i],"anything")==0)sta[i]=3;else if(strcmp(str[i],"statements")==0)sta[i]=1;else sta[i]=2;}h=m=0;for(i=1;i<=n;i++){if(rk[i]%4<2)left[++h]=i;elseright[++m]=i;}memset(match,0,sizeof(match));for(i=1;i<=h;i++){for(j=1;j<=m;j++){if((sta[left[i]]==3||sta[right[j]]==3)||abs(rk[left[i]-rk[right[j]]])==2)match[i][j]=1;}}res=hungary();printf("%d\n",res);for(i=1;i<=m;i++){if(~link[i]){int num1=left[link[i]];int num2=right[i];if(sta[num1]==2)swap(num1,num2);if(sta[num2]==1)swap(num1,num2);printf("%s %s\n",name[num1],name[num2]);}}}return 0; }?
轉載于:https://www.cnblogs.com/dashuzhilin/p/4652438.html
總結
以上是生活随笔為你收集整理的URAL 1721 Two Sides of the Same Coin(二分图匹配,输出匹配对象)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 给Android程序员的六个建议
- 下一篇: 阴影效果 ShadowLayout 布局