题目:http://www.lightoj.com/volume_showproblem.php?problem=1003
题意:有很多种饮料,有如下条件:要喝一种饮料前必须喝给定的另外一种饮料。问在给定的条件中能不能喝完所有饮料
思路:饮料名是英文字母,首先映射成数字。不能喝完所有的饮料的原因必定是因为两种饮料互为先决条件(不一定是直接的),也就是出现了环,因为有向图,所以用拓扑排序排一下序,统计能排多少个点,能排序的点数若不等于总点数,必然是出现了环
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <string>
using namespace std;
const int N = 10010;
int deg[N];
struct edge
{
int to, next;
}g[10010];
int cnt, head[N];
int cas;
void add_edge(int v, int u)
{
g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;
}
bool toposort(int num)
{
queue<int> que;
int cnt = 0;
for(int i = 0; i < num; i++)
if(deg[i] == 0) que.push(i), cnt++;
while(! que.empty())
{
int v = que.front(); que.pop();
for(int i = head[v]; i != -1; i = g[i].next)
if(--deg[g[i].to] == 0) que.push(g[i].to), cnt++;
}
return num == cnt;
}
int main()
{
int t, m;
char s1[20], s2[20];
scanf("%d", &t);
while(t--)
{
scanf("%d", &m);
int num = 0;
map<string, int> mpa;
cnt = 0;
memset(head, -1, sizeof head);
memset(deg, 0, sizeof deg);
for(int i = 0; i < m; i++)
{
scanf("%s%s", s1, s2);
if(mpa.find(s1) == mpa.end()) mpa[s1] = num++;
if(mpa.find(s2) == mpa.end()) mpa[s2] = num++;
deg[mpa[s2]]++;
add_edge(mpa[s1], mpa[s2]);
}
if(toposort(num)) printf("Case %d: Yes\n", ++cas);
else printf("Case %d: No\n", ++cas);
}
return 0;
}