这题目做了我好久,以前从来没做过,现在基础还没打好,代码是网上的,只能说稍微有理解那么一点,如果有什么好的方法解这道题,希望各位能够给点意见
时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte
总提交:106 测试通过:41
总提交:106 测试通过:41
描述
John先生晚上写了n封信,并相应地写了n个信封将信装好,准备寄出。但是,第二天John的儿子Small John将这n封信都拿出了信封。不幸的是,Small John无法将拿出的信正确地装回信封中了。
编程任务
将Small John所提供的n封信依次编号为1,2,...,n; 且n个信封也依次编号为1,2,...,n。假定Small John能提供一组信息:第i封信肯定不是装在信封j中。请编程帮助Small John,尽可能多地将信正确地装回信封。输入
本题有多组输入数据,你必须处理到EOF为止。
每组数据的第一行是一个整数n(n≤100)。信和信封依次编号为1,2,…,n。
接下来的各行中每行有2个数i和j,表示第i封信肯定不是装在第j个信封中。输入最后一行是2个0,表示结束。
输出
对于每组数据,输出的各行中每行有2个数i和j,表示第i封信肯定是装在第j个信封中。请按信的编号i从小到大顺序输出。若不能确定正确装入信封的任何信件,则输出“none”。
每组输出结束之后,输出一个空行。
样例输入
3
1 2
1 3
2 1
0 0
1 2
1 3
2 1
0 0
样例输出
1 1
#include<iostream>
#include<cstring>
using namespace std;
int tot=0,n,link[105],f[105];
bool map[105][105]={0},v[105];
bool find(int x)
{
int i;
for(i=1;i<=n;i++)
if(!map[x][i]&&!v[i])
{ v[i]=1;
if(link[i]==0||find(link[i])) //找增广路
{ link[i]=x;return true; }
}
return false;
}
int hungary()
{
int ans=0,i;
memset(link,0,sizeof(link));
for(i=1;i<=n;i++)
{ memset(v,0,sizeof(v));
if(find(i))ans++; //增广成功。
}
return ans;
}
void solve()
{
int i,t; bool flag=1;
t=hungary();
memcpy(f,link,sizeof(link));//记录第一次的匹配情况。
if(t!=n)cout<<"none";
else for( i=1;i<=n;i++)
{
map[f[i]][i]=1;//断边
t=hungary();
if(t!=n){cout<<f[i]<<" "<<i<<endl;flag=0;}
map[f[i]][i]=0;//恢复
}
if(flag)cout<<"none";//输出为空。
}
int main()
{
int i,j,x,y;
cin>>n;
while (1)
{
cin>>x>>y;
if(x+y==0)break;
map[x][y]=1;
}
solve();
return 0;
}