拓扑排序

烦人的幻灯片(slides)

样例
	4
	6 22 10 20
	4 18 6 16
	8 20 2 18
	10 24 4 8
	9 15
	19 17
	11 7
	21 11

2f2LsP.png

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
struct ne{
	int xa;
	int ya;
	int xb;
	int yb;
};
struct nee{
	int a;
	char b;
};
nee ans[500];
ne ppt[50];
int po[50][50];
int in[500];
int on[500];
int can[500];
int t;
int n;
int x,y;
int now;
queue<int> q;
int cmp(nee aa,nee bb)
{
	return aa.b<bb.b;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d%d",&ppt[i].xa,&ppt[i].xb,&ppt[i].ya,&ppt[i].yb);
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&x,&y);
		for(int j=1;j<=n;j++) // 判断当前点上有哪些幻灯片 
		{
			if(x>=ppt[j].xa&&x<=ppt[j].xb&&y>=ppt[j].ya&&y<=ppt[j].yb)
			{
				po[i][j]=1; //i为点的序号,j为幻灯片的序号 
				in[i]++; //该点上的幻灯片数++ 
			}
		}
	}
	for(int i=1;i<=n;i++) //找只经过一个幻灯片的点,入队 
	{
		if(in[i]==1) q.push(i);
	}
	while(!q.empty()) // 拓扑排序 
	{
		now=q.front();
		q.pop();
		for(int i=1;i<=n;i++) //找到该点,并寻找该点经过的所有幻灯片 
		{
			if(po[now][i]==1&&can[i]==0) // 找到并且该点没被访问过 
			{
				ans[++t].b=(i-1+'A'); //幻灯片编号 
				can[i]=1; //标记为已访问 
				ans[t].a=now; //点的编号 
				for(int j=1;j<=n;j++) //去掉该幻灯片,并将该幻灯片上所有点的“入度” 减一 
				{
					if(po[j][i]==1) in[j]--;
					if(in[j]==1) //若某个点的入度为一,即只对应一张幻灯片,则将该点入队 
					q.push(j);
				}
				continue;
			 }
			
		}
	}
	sort(ans+1,ans+1+t,cmp); //将幻灯片和点的对应组按幻灯片数按序排列 
	if(t==n){ 
		for(int i=1;i<=t;i++)
		printf("%c %d\n",ans[i].b,ans[i].a);
		printf("\n");
	}
	else
	printf("None\n");
	return 0;
}

病毒(virus)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
string fro;
string now;
string s;
queue<int> q;
int a[50][50];
int in[50];
int ss[50];int t=0;
bool chr[50];
int nn;
int cp[50];int tt=0;
int maxn=0;
int main()
{
	memset(in,0x3f,sizeof(in)); //开始把26个字母的入度全设为无穷大 
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		cin>>now;
		if(i==1){
			fro=now;
			continue;
		}
		if(fro==now) continue;
		for(int j=0;j<min(now.length(),fro.length());j++)
		{
			if(fro[j]!=now[j]){
				a[int(fro[j])-'a'+1][int(now[j])-'a'+1]=1; 
			    chr[int(fro[j])-'a'+1]=chr[int(now[j])-'a'+1]=1; //把出现过的字母标记为出现过 
			    if(in[int(fro[j])-'a'+1]>100) in[int(fro[j])-'a'+1]=0; //
			    if(in[int(now[j])-'a'+1]>100) in[int(now[j])-'a'+1]=0; //把出现的字母的入度设为零 
				in[int(now[j])-'a'+1]++;
				break;
			}
		}
		fro=now; //实现新旧交替 
	}
	for(int i=1;i<=26;i++) //统计出现过的字母数量 
	if(chr[i]==1){
		maxn++;
	} 
	cin>>s;
	for(int i=1;i<=26;i++) //把入度为零的字母入队 
	{
		if(in[i]==0){
			q.push(i);
		}
	}
	while(!q.empty()) // 拓扑排序 
	{
		nn=q.front();
		q.pop();
		ss[nn-1+'a']='a'+t++; //ss[]表示字母对应的乱码 
		for(int i=1;i<=26;i++)
		{
			if(a[nn][i]==1) {
				in[i]--;
				if(in[i]==0) q.push(i);	
			}
		}
	}
	for(int i=0;i<s.length();i++) //如果出现了之前没出现的字母,输出0 
	if(chr[(s[i]-'a'+1)]!=1){
		printf("0\n");
		return 0;
	}
	if(t!=maxn){  //判断有无回路 
		printf("0\n");
		return 0;
	}
	for(int i=0;i<s.length();i++) //进行乱码翻译 
	printf("%c",ss[s[i]]);
	printf("\n");
		return 0;
}
/*
7
cebdbac
cac
ecd
dca
aba
bac
word
wwwcedab

*/
posted @ 2021-09-26 11:36  Du_zk  阅读(41)  评论(0编辑  收藏  举报