您的位置:首页 > 其它

1222 信与信封问题

2018-09-04 16:13 381 查看

1222 信与信封问题

链接

 

分析:

  先二分图匹配一下, 如果不存在完美匹配(n个点全匹配成功),则直接输出none,表示有一封信不能被任何一个信封装下,根据题目可知,一定会有一个可行的方案,所以是不符的,直接输出none。(想了很长时间为什么,看了一遍题目才想过来。。。感觉输出“不合法”更好一些,或许可能存在可以确定的信呢。。)

  然后判断每个点是不是有唯一的匹配,删除当前匹配边后,还有没有其他的匹配。判断是不是可以确定的信封。

  

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>

using namespace std;

const int N = 110;

int G

,match
,T
;
bool vis
;
int n;

inline int read() {
int x = 0,f = 1;char ch=getchar();
for (; !isdigit(ch); ch=getchar()) if(ch=='-')f=-1;
for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';
return x*f;
}
bool dfs(int u) {
for (int v=1; v<=n; ++v) {
if (G[u][v] && !vis[v]) {
vis[v] = true;
if (!match[v] || dfs(match[v])) {
match[v] = u;T[u] = v;
return true;
}
}
}
return false;
}
int main() {
n = read();
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j) G[i][j] = 1;
int a = read(),b = read();
while (a + b) {
G[a][b] = 0; // 左边的a与右边的b的边,不能更新G[b][a](左边的b,右边的a)
a = read(),b = read();
}
int ans = 0;
for (int i=1; i<=n; ++i) {
memset(vis,false,sizeof(vis));
if (dfs(i)) ans++;
}
if (ans != n) {printf("none");return 0;}
bool flag = false;
for (int u=1; u<=n; ++u) {
memset(vis,false,sizeof(vis));
int v = T[u];
G[u][v] = 0;
match[v] = 0;T[u] = 0;
if (!dfs(u)) {
printf("%d %d\n",u,v);
match[v] = u;T[u] = v;flag = true;
}
G[u][v] = 1;
}
if (!flag) printf("none");
return 0;
}

 

 

 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: