http://acm.timus.ru/problem.aspx?space=1&num=1218
缩点后形成树 树的根节点 就是有可能获胜的点
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
#define LL long long
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int INF=0x3f3f3f3f;
const int N=205;
struct node
{
string name;
int a[3];
}mem[N];
bool beat[N][N];
int low[N],dfn[N],deep;
bool in[N],visited[N],maybewin[N];
int f[N];
stack<int>St;
int n;
void Tarjan(int x)
{
low[x]=dfn[x]=deep++;
visited[x]=true;
St.push(x);
in[x]=true;
for(int l=1;l<=n;++l)
{
if(beat[x][l]==false)
continue;
if(!visited[l])
{
Tarjan(l);
low[x]=min(low[x],low[l]);
}else if(in[l])
{
low[x]=min(low[x],dfn[l]);
}
}
if(low[x]==dfn[x])
{
while(St.top()!=x)
{
f[St.top()]=x;
in[St.top()]=false;
St.pop();
}
f[St.top()]=x;
in[St.top()]=false;
St.pop();
}
}
bool Kill(int i,int j)
{
int k=0;
for(int l=0;l<3;++l)
if(mem[i].a[l]>mem[j].a[l])
++k;
if(k>=2)
return true;
return false;
}
int main()
{
//freopen("data.txt","r",stdin);
while(cin>>n)
{
for(int i=1;i<=n;++i)
{
cin>>mem[i].name;
for(int j=0;j<3;++j)
cin>>mem[i].a[j];
}
memset(beat,false,sizeof(beat));
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(Kill(i,j))
beat[i][j]=true;
memset(visited,false,sizeof(visited));
for(int i=1;i<=n;++i)
if(!visited[i])
Tarjan(i);
memset(maybewin,true,sizeof(maybewin));
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
if(beat[i][j]&&f[i]!=f[j])
maybewin[f[j]]=false;
}
for(int i=1;i<=n;++i)
{
if(maybewin[f[i]])
cout<<mem[i].name<<endl;
}
}
return 0;
}
浙公网安备 33010602011771号