给定n对信息,是1-->2有一对交换生,能交换的条件是2-->1也有一对交换生,问能否顺利交换。
思路:用有向图模拟,如果1-->2有一对,那么就优先判断2-->1有没人交换,有的话,就不用加边了,直接标记那条边用了即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 5e5+20; int n,now; struct edge { int u,v,w; int id;//区分无向图的时候用的,id相同就是同一条边 int next; } e[maxn*2]; //这个存的是边,要插入两次,所以要*2 int first[maxn]; //这个表示什么【顶点】的第一条边,所以只用maxn大小即可 int num=0;//从1开始,这样就是没0号这条边。方便判断。所以每次先++num再放边!! void add (int u,int v,int w) { ++num; //这个num是边的编号 e[num].u=u; e[num].v=v; e[num].w=w; e[num].id=0; e[num].next=first[u];//下一条边是这个顶点的第一条边 first[u]=num;//这个顶点的第一条边是编号为num的这条 return ; } void work () { num = 0; now = 0; memset(first,0,sizeof first); for (int i=1;i<=n;++i) { int u,v; scanf("%d%d",&u,&v); bool flag = 1; for (int j = first[v]; j ; j = e[j].next) { if (e[j].v == u && e[j].id == 0) { flag = 0; e[j].id=1; now--; break; } } if (flag) { now++; add(u,v,1); } } if (now==0) { printf ("YES "); } else printf ("NO "); } int main() { #ifdef local freopen("data.txt","r",stdin); #endif while (scanf("%d",&n)!=EOF && n) work(); return 0; }