题意:逐条给出一些大小关系,问能否根据这些关系排出一个严格递增的序列。1.如果可以,指明给到第几条能排出,并给出序列;2.如果无法排成严格递增,输出不行;3.如果无法排成序列,输出不行和当前条数。
解:将n>m视作从n到m连一条有向边,那么这道题就是一个显然的拓扑排序。但是由于要判断在哪里可以确定序列,所以每加一条就要跑一边topo。拓扑排序排下来有三种情况,一是能形成拓扑序,但有多条事件处于同一级别,到这里还不能判断最终能否符合要求,因为可能有新的边加入;二是形成拓扑序,且是一条链,这是可以直接输出,然后把后面输入读进来就好。三是少于n个结点加入拓扑序,也就是说有环,可以直接输出无解,然后读入后面数据。
其实一开始的想法是等有了n个结点再扔进去跑,但有n个结点不能保证该连的边都连了,不如暴力处理再说。
顺带一提题单上做掉的会标成绿色,挺好玩的x
代码:
1 #include<stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <queue> 5 #include <vector> 6 using namespace std; 7 #define ll long long 8 #define maxx 35 9 #define inf 0x3f 10 const int mod=1e9+7; 11 //#define int long long 12 int n,m; 13 int in[maxx]={0},tin[maxx]={0}; 14 vector<int> e[maxx]; 15 vector<int> ans; 16 int topo(){ 17 ans.clear(); 18 for(int i=0;i<n;i++) 19 tin[i]=in[i]; 20 queue<int> q; 21 for(int i=0;i<n;i++) 22 if(in[i]==0) 23 q.push(i); 24 int flag=0; 25 while(!q.empty()){ 26 if(q.size()>1) 27 flag=1; 28 int now=q.front(); 29 q.pop(); 30 ans.push_back(now); 31 for(int i=0;i<e[now].size();i++){ 32 int to=e[now][i]; 33 tin[to]--; 34 if(!tin[to]) 35 q.push(to); 36 } 37 } 38 if(ans.size()<n) 39 return -1; 40 if(flag) 41 return 0; 42 return 1; 43 } 44 signed main() { 45 while(~scanf("%d%d",&n,&m)) { 46 if(n==0&&m==0) 47 break; 48 memset(in,0,sizeof in); 49 for(int i=0;i<maxx;i++) 50 e[i].clear(); 51 52 int idx=0,flag=0; 53 for (int i = 1; i <= m; i++) { 54 char s[20]; 55 scanf("%s", s); 56 if(flag) 57 continue; 58 e[s[0] - 'A'].push_back(s[2] - 'A'); 59 in[s[2] - 'A']++; 60 int res=topo(); 61 if(res==1) 62 idx=i,flag=1; 63 if(res==-1) 64 idx=i,flag=2; 65 } 66 if(flag==1) { 67 printf("Sorted sequence determined after %d relations: ", idx); 68 for (int j=0;j<ans.size();j++) 69 printf("%c", ans[j] + 'A'); 70 printf(".\n"); 71 } 72 else if(flag==2) 73 printf("Inconsistency found after %d relations.\n",idx); 74 else 75 printf("Sorted sequence cannot be determined.\n"); 76 } 77 return 0; 78 }