Atcoder ABC 139E

Atcoder ABC 139E

题意:

n支球队大循环赛,每支队伍一天只能打一场,求最少几天能打完。

解法:

考虑抽象图论模型,既然一天只能打一场,那么就把每一支球队和它需要交手的球队连边。
求出拓扑序,每次从入度为0的点进行拓扑排序,并把答案加1,删去所有出度,重复该操作。
如果形成环的话就无解。

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define LL long long
#define N 1000010
#define M 1010

using namespace std;

struct Edge {
	int from, to; 
}e[N]; 

int n,num,cnt,tot,ans;
int head[N],a[M][M],node[M][M];
int inq[N],t[N],day[N]; 

inline void add_edge(int x,int y) {
    e[++cnt].from = y;
    e[cnt].to = head[x];
    head[x] = cnt;
}
void topsort() {
	for(int i = 1; i <= tot; i++) {
		int u = t[i]; 
		for(int j = head[u]; j; j = e[j].to) {
			int v = e[j].from; 
			day[v] = day[u] + 1; 
			inq[v]--; 
			if(!inq[v])t[++tot] = v; 
		}
	}
	for(int i = 1; i <= num; i++)
		ans = max(ans, day[i]); 
}

int main() {
	scanf("%d",&n); 
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j < n; j++) {
			scanf("%d",&a[i][j]); 
			if(!node[i][j] && !node[j][i])
				node[i][j] = node[j][i] = ++num; 
		}
	}
	for(int i = 1; i <= n; i++) {
		for(int j = 2; j < n; j++) {
			add_edge(node[i][a[i][j-1]], node[i][a[i][j]]); 
			inq[node[i][a[i][j]]]++; 
		}
	}
	for(int i = 1; i <= num; i++) {
		if(!inq[i]) {
	  		t[++tot] = i; 
	  		day[i] = 1; 
	  	}
	}
	topsort(); 
	if(tot != num) puts("-1"); 
	else printf("%d\n", ans); 
    //system("pause");
	return 0; 
}
posted @ 2019-09-02 21:23  西窗夜雨  阅读(198)  评论(0编辑  收藏  举报