题意与分析
2018ICPC北京站A题。
题意是这样的,给定若干人的武力值大小(A B
的意思是A比B厉害),问到第几行会出现矛盾。
这题不能出现思维定势,看到矛盾就是矛盾并查集——A>B、A>C是不能推出B>C或者B<C的。相反,大于小于是一种偏序关系,是可以建立有向图的。那么,如果这个有向图中出现了环,就是矛盾的。
问题于是转化为有向图判环问题,这里简单说一下有向图和无向图的判环方法。
a) 无向图
- 删除所有度<=1的顶点及相关的边,并将另外与这些边相关的其它顶点的度减一。
- 将度数变为1的顶点排入队列,并从该队列中取出一个顶点重复步骤一。
最后如果最后还有未删除顶点,则存在环,否则没有环。
b) 有向图
对于n个节点的有向图,令cnt = 0。
- 将所有入度为0的节点入队;
- 将队头节点v出队,cnt++,直至队列为空;
- 遍历与v相连的节点,并将相连节点的入度减一,若入度变为0,将此节点入队。
最后,若cnt==n,访问到所有节点,完成拓扑排序(这是出队顺序的意义),否则,存在环。
代码
/* ACM Code written by Sam X or his teammates.
* Filename: a.cpp
* Date: 2018-11-17
*/
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PB emplace_back
#define MP make_pair
#define fi first
#define se second
#define rep(i,a,b) for(repType i=(a); i<=(b); ++i)
#define per(i,a,b) for(repType i=(a); i>=(b); --i)
#define ZERO(x) memset(x, 0, sizeof(x))
#define MS(x,y) memset(x, y, sizeof(x))
#define ALL(x) (x).begin(), (x).end()
#define QUICKIO
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
using namespace std;
using pi=pair<int,int>;
using repType=int;
using ll=long long;
using ld=long double;
using ull=unsigned long long;
const int MAXN=25;
vector<int> G[MAXN];
vector<pi> edges;
void add_edge(int u,int v)
{
edges.PB(u,v);
G[u].PB(edges.size()-1);
}
int vis[MAXN];
int n;
unordered_map<string,int> ma;
vector<string> idx;
int gh(string str)
{
if(ma.find(str)==ma.end())
{
idx.PB(str);
return ma[str]=idx.size()-1;
}
return ma[str];
}
bool has_loop()
{
int cnt=0;
queue<int> q;
int deg[MAXN];
ZERO(deg);
rep(i,0,int(edges.size())-1)
{
deg[edges[i].se]++;
}
rep(i,0,idx.size()-1)
if(deg[i]==0)
{
q.push(i);
}
while(!q.empty())
{
//cout<<"Now: "<<q.front()<<endl;
cnt++;
auto now=q.front(); q.pop();
rep(i,0,int(G[now].size())-1)
{
deg[edges[G[now][i]].se]--;
if(deg[edges[G[now][i]].se]==0)
q.push(edges[G[now][i]].se);
}
}
//cout<<cnt<<" and "<<idx.size()<<endl;
return cnt!=idx.size();
}
int
main()
{
while(cin>>n)
{
bool ok=true;
idx.clear();
ma.clear();
rep(i,0,20) G[i].clear();
edges.clear();
rep(i,1,n)
{
string stra,strb;
cin>>stra>>strb;
if(!ok) continue;
int u=gh(stra), v=gh(strb);
//cout<<"Add: "<<u<<" "<<v<<endl;
add_edge(u,v);
if(has_loop())
{
cout<<stra<<" "<<strb<<endl;
ok=false;
}
}
if(ok) cout<<0<<endl;
}
return 0;
}