UESTC_排名表 2015 UESTC Training for Graph Theory<Problem I>
2015-06-12 01:10
453 查看
I - 排名表
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)Submit Status
暑假前集训已经过了一半了,我们将会把当前排名公布出来。但是此刻秋实大哥却心急火燎,因为他不慎把排名删除了。
一共有n个人参加排名,每个人都有一个名次,没有哪两个人的名次是相同的。现在秋实大哥掌握的一些情报,比如Ai的名次要先于Bi。(编号从1开始)
你能帮秋实大哥恢复出排名表吗?
Input
第一行一个数字 T (T≤10),表示测试数据组数每组测试数据,第一行两个数 n(1≤n≤200)和 m(0≤m≤40000),接下来m行,每行两个数a和b(1≤a,b≤N),表示a的名次要先于b
Output
对于每组测试数据,输出一行,从1号到n号每个人的名次。如果有多个解,让编号为1的人的名次尽量小,然后让编号为2的人的名次尽量小,然后让编号为3的人的名次尽量小......
如果没有解,输出−1
Sample input and output
Sample Input | Sample Output |
---|---|
5 4 0 4 1 1 1 4 2 1 2 2 1 4 1 2 1 4 1 3 2 | 1 2 3 4 -1 -1 2 1 3 4 1 3 2 4 |
Hint
注意可能会有重边解题思路:
首先,本题正向拓扑排序是不行的,即如果这样建边:
U 的名次先于 V , 即 V 向 U连边
因为题意比较绕,下文都这样叙述:
排名号越高,其名次越低,第一名的排名号是 1 ,它的名次是最高的.
我们按照 v 向 u建边,意思是v的排名号高于u.
无法保证
让编号为1的人的名次尽量小,然后让编号为2的人的名次尽量小,然后让编号为3的人的名次尽量小.
è 让编号为 1 的人的排名号尽量大,然后让编号为 2 的人的排名号尽量大….
我们拓扑排序的顺序是这样的:
每次寻找入度为 0 的点,将排名号赋给这个点,删边,重复.
如果有多个点入度都是 0 呢?我们不假思索的这样想:
我们为了保证题目条件,会使得我们会尽量保证这个点的编号尽量小(这样我们看起来符合了题目条件:编号小的人排名号尽量高),但是我们忽略了,题目要求是先尽力保证编号1的人,之后才是编号2的人….
所以,正向建边是错误的
注意,上面的证明非常不严格(Even it's a mistake),如果小伙伴谁有更好的证明,可在下面回复
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #define pb push_back using namespace std; const int maxn = 200 + 10; int n,m,c[maxn],indig[maxn]; vector<int>E[maxn]; bool existedge[maxn][maxn]; int out[maxn]; bool dfs(int cur) { if (c[cur] == 1) return true; c[cur] = -1; for(int i = 0 ; i < E[cur].size() ; ++ i) { int nextnode = E[cur][i]; if (c[nextnode] == -1) return false; if (!c[nextnode] && !dfs(nextnode)) //exist 环 return false; } c[cur] = 1; return true; } typedef struct point { int id,indig; friend bool operator < (const point & x,const point & y) { return x.indig < y.indig; } point(int id,int indig) { this->id = id , this->indig = indig; } }; vector<point>v; bool used[maxn]; void ansset() { memset(used,false,sizeof(used)); for(int i = 1 ; i <= n ; ++ i) v.pb(point(i,indig[i])); sort(v.begin(),v.end()); int rank = 0; for(int i = 1 ; i <= n ; ++ i) { int choose = v[0].id; int pos = 0; while( pos < v.size() && !v[pos].indig) choose = max(choose,v[pos++].id); out[choose] = n - rank++; used[choose] = true; for(int i = 0 ; i < E[choose].size() ; ++ i) indig[E[choose][i]]--; v.clear(); for(int i = 1 ; i <= n ; ++ i) if(!used[i]) v.pb(point(i,indig[i])); sort(v.begin(),v.end()); } } int main(int argc,char *argv[]) { int Case; scanf("%d",&Case); while(Case--) { scanf("%d%d",&n,&m); memset(c,0,sizeof(c)); memset(existedge,false,sizeof(existedge)); memset(indig,0,sizeof(indig)); while(m--) { int u,v; scanf("%d%d",&u,&v); if (existedge[v][u]) continue; E[v].pb(u); existedge[v][u] = true; indig[u] ++; } int ans = 1; for(int i = 1 ; i <= n ; ++ i) if (!dfs(i)) { ans = 0; break; } if (!ans) printf("-1\n"); else { v.clear(); ansset(); for(int i = 1 ; i <= n ; ++ i) i == 1 ? printf("%d",out[i]) : printf(" %d",out[i]); printf("\n"); } for(int i = 1 ; i <= n ; ++ i) E[i].clear(); } return 0; }
相关文章推荐
- UESTC_韩爷的情书 2015 UESTC Training for Graph Theory<Problem H>
- UESTC_Big Brother 2015 UESTC Training for Graph Theory<Problem G>
- UESTC_传输数据 2015 UESTC Training for Graph Theory<Problem F>
- UESTC_树上的距离 2015 UESTC Training for Graph Theory<Problem E>
- UESTC_邱老师的脑残粉 2015 UESTC Training for Graph Theory<Problem D>
- UESTC_秋实大哥与时空漫游 2015 UESTC Training for Graph Theory<Problem C>
- UESTC_秋实大哥带我飞 2015 UESTC Training for Graph Theory<Problem B>
- UESTC_秋实大哥与连锁快餐店 2015 UESTC Training for Graph Theory<Problem A>
- Mac Error Create Android Project - “Errors running builder 'Android Resource Manager' on project”
- Arduino 入门程序示例之一片 LED(2015-06-11)
- android更新UI的几种方法
- Arduino 入门程序示例之一排 LED(2015-06-11)
- build erlang 17.5
- 如何让设计师发挥潜能?
- Implement Stack using Queues
- 通过简单的方法适应iOS7中的UIViewController,同时兼容iOS6
- 给iOS工程增加Daily Build
- iOS5中UIViewController的新方法
- DuiVision开发教程(18)-弹出窗
- duilib中各控件响应的消息类型