pat-05复习 图部分剩余

 //1111 
 //测试点二有问题 
 #include<bits/stdc++.h>
 using namespace std;
 vector<int> pred[510],pret[510],temp,temp1,ansd,anst;
 int distd[510],distt[510];
 int a[510][510],t[510][510],visit1[510],visit2[510];
 const int inf=1000000000;
 int ss,mint=inf,mins=inf;//qidm
 void dfs1(int dd){
 	//end
 	if(dd==ss){
 	 temp.push_back(dd);
	  int sumt=0;
	  for(int j=temp.size()-1;j>=1;j--){//双向 
	  	sumt=t[temp[j] ][temp[j-1] ];//双重索引又错误 
	  }
	  if(sumt<mint){
	  	mint=sumt;
	  	ansd=temp;
	  }	
	 temp.pop_back();
	 return;
	 }
	 temp.push_back(dd);
 	for(int i=0;i<pred[dd].size();i++){
 		dfs1(pred[dd][i]);
	 }
	 temp.pop_back();
 }
 void dfs2(int dd){
 	//end
 	if(dd==ss){
 	 temp1.push_back(dd);
	  if(temp1.size()<mins){
	  	mins=temp1.size();
	  	anst=temp1;
	  }
	  
	 temp1.pop_back();
	 return;
	 }
	 temp1.push_back(dd);
 	for(int i=0;i<pret[dd].size();i++){
 		dfs2(pret[dd][i]);
	 }
	 temp1.pop_back();
 }
 int main(){
 	fill(a[0],a[0]+510*510,inf);
 	fill(t[0],t[0]+510*510,inf);
 	fill(distd,distd+510,inf);
 	fill(distt,distt+510,inf);
 	int n,m,_1,_2,_3,_4,_5;
 	scanf("%d%d",&n,&m);
 	for(int i=0;i<m;i++){
 		scanf("%d%d%d%d%d",&_1,&_2,&_3,&_4,&_5);
 		if(_3==1){
 			a[_1][_2]=_4;
 			t[_1][_2]=_5;
		 }else{
		 	a[_1][_2]=a[_2][_1]=_4;
		 	t[_1][_2]=t[_2][_1]=_5;
		 }
	 }
	 int end;
	 scanf("%d%d",&ss,&end);
	 distd[ss]=0;
	 distt[ss]=0;
	 for(int i=0;i<n;i++){
	 	int u=-1,min=inf;
	 	for(int j=0;j<n;j++){
	 		if(visit1[j]==0&&distd[j]<min){
	 			min=distd[j];
	 			u=j;
			 }
		 }
		 if(u==-1) break;
		 visit1[u]=1;
		 for(int v=0;v<n;v++){
		 	if(visit1[v]==0&&a[u][v]!=inf){
		 		if(distd[v]>distd[u]+a[u][v]){
		 			distd[v]=distd[u]+a[u][v];
		 			pred[v].clear();
		 			pred[v].push_back(u);
				 }else if(distd[v]==distd[u]+a[u][v]){
				 	pred[v].push_back(u);
				 }
			 }
		 }
	 }
	 dfs1(end);
	  for(int i=0;i<n;i++){
	 	int u=-1,min=inf;
	 	for(int j=0;j<n;j++){
	 		if(visit2[j]==0&&distt[j]<min){
	 			min=distt[j];
	 			u=j;
			 }
		 }
		 if(u==-1) break;
		 visit2[u]=1;
		 for(int v=0;v<n;v++){
		 	if(visit2[v]==0&&t[u][v]!=inf){
		 		if(distt[v]>distt[u]+t[u][v]){
		 			distt[v]=distt[u]+t[u][v];
		 			pret[v].clear();
		 			pret[v].push_back(u);
				 }else if(	distt[v]==distt[u]+t[u][v]){
				 	pret[v].push_back(u);
				 }
			 }
		 }
	 }
	 dfs2(end);
	 if(ansd==anst){
	 	printf("Distance = %d; Time = %d:",distd[end],distt[end]);
	 	for(int i=ansd.size()-1;i>=0;i--){
	 		if(i!=ansd.size()-1)printf(" ->");
	 		printf(" %d",ansd[i]);//注意一下最后有没有空格 
		 }
		 
	 }else{
	 	printf("Distance = %d:",distd[end]);
	 	for(int i=ansd.size()-1;i>=0;i--){
	 		if(i!=ansd.size()-1)printf(" ->");
	 		printf(" %d",ansd[i]);
	 	}
	 	printf("\n");
	 	printf("Time = %d:",distt[end]);
	 	for(int i=anst.size()-1;i>=0;i--){
	 		if(i!=anst.size()-1)printf(" ->");
	 		printf(" %d",anst[i]);
	 	}
	 	//printf("\n");
	 }
	 return 0;
 }
//1122 先判断连不连通 
#include<bits/stdc++.h>
 using namespace std;
 int a[500][500];
 //const int inf=1000000000;
 int main(){
 	fill(a[0],a[0]+500*500,0);//就是为了判断路径不存在的情况,每一个小栗子都要弄明白 
 	int n,m,_1,_2;
 	scanf("%d%d",&n,&m);
 	for(int i=0;i<m;i++){
 		scanf("%d%d",&_1,&_2);
 		a[_1][_2]=a[_2][_1]=1;
	 }
	 int k,_3,_4;
	 scanf("%d",&k);
	 for(int i=0;i<k;i++){
	 	scanf("%d",&_3);
	 	int _00,_001;
	 	set<int> num;
	 	vector<int> path; 
	 	num.clear();
	 	for(int j=0;j<_3;j++){
	 		scanf("%d",&_4);
	 		path.push_back(_4);
			 if(j==0) _00=_4;
			 if(j==_3-1) _001=_4;
			 num.insert(_4);
		 }int flag=1;
		 for(int i=1;i<path.size();i++){
		 	if(a[path[i]][path[i-1]]==0){
		 	flag=0;
			 break;	
			 }
		 }
		 if(_3!=n+1) printf("NO\n");
		 else if(_00!=_001) printf("NO\n");
		 else if(num.size()!=n) printf("NO\n");
		 else if(flag==0) printf("NO\n");
		 else printf("YES\n");
	 }
	 return 0;
 }
//1126 
#include<bits/stdc++.h>
 using namespace std;
 int visit[510],n,a[510][510],dg[510];
 void dfs(int index){
 	visit[index]=1;
 	for(int i=1;i<=n;i++){
 		if(visit[i]==0&&a[index][i]!=0){
 			dfs(i);
		 }
	 }
 }
 int main(){
 	int m,_1,_2;//上面已经声明过n下面又声明重复声明出错 
 	scanf("%d%d",&n,&m);
 	for(int i=0;i<m;i++){
 		scanf("%d%d",&_1,&_2);
 		a[_1][_2]=a[_2][_1]=1;
 		dg[_1]++;
 		dg[_2]++;
	 }
	 int cnt=0;
	 for(int i=1;i<=n;i++){
	 	if(visit[i]==0){
	 	dfs(i);
		cnt++;
		 }
		 
	 }
	 int even=0,odd=0;
	 for(int i=1;i<=n;i++){
	 	if(dg[i]%2==0) even++;
	 	else odd++;
	 	if(i!=1) printf(" ");
	 	printf("%d",dg[i]);
	 }
	 printf("\n");
	 if(cnt!=1) printf("Non-Eulerian");
	 else if(odd==2) printf("Semi-Eulerian");
	 else if(odd==0) printf("Eulerian");
	 else printf("Non-Eulerian");
	 return 0;
 }
//1154 
#include<bits/stdc++.h>
 using namespace std;
 struct node{
 	int ll,rr;
 };
 vector<node> a;
 vector<int> b;
 int main(){
 	int n,m,_1,_2;
 	scanf("%d%d",&n,&m);
 	for(int i=0;i<m;i++){
 		scanf("%d%d",&_1,&_2);
 		a.push_back({_1,_2});
	 }
	 int k,_3;
	 scanf("%d",&k);
	 for(int i=0;i<k;i++){
	 	b.clear();
	 	set<int>num;
	 	for(int j=0;j<n;j++){
	 	scanf("%d",&_3);
		 b.push_back(_3);
		 num.insert(_3);	
		 }
		 int flag=1;
	 	for(int q=0;q<a.size();q++){
	 		if(b[a[q].ll]==b[a[q].rr]){//if多个修改项没加括号	 
			 printf("No\n");
			 flag=0;
			 break;
		   }
		 }
		 if(flag==1){
		 	printf("%d-coloring\n",num.size());
		 }
	 }
	 return 0;
 }
//1150
#include<bits/stdc++.h>
 using namespace std;
 const int inf=1000000000;
 int a[510][510],_4;
 vector<int> jm;
 void dfs(int &sum){
 	//end
 	sum=0;
 	for(int i=1;i<_4;i++){
 		if(a[jm[i-1]][jm[i]]!=inf)
		 sum+=a[jm[i-1]][jm[i]]; 
		 else{
		 	sum=inf;
		 	break;
		 }
	 }
 }
 int main(){
 	fill(a[0],a[0]+510*510,inf);
 	int n,m,_1,_2,_3;
 	scanf("%d%d",&n,&m);
 	for(int i=0;i<m;i++){
 		scanf("%d%d%d",&_1,&_2,&_3);
 		a[_1][_2]=a[_2][_1]=_3;
	 }
	 int k,_5,min=inf,minindex;
	 scanf("%d",&k);
	 for(int i=1;i<=k;i++){
	 	set<int>num;
	 	jm.clear();
	 	scanf("%d",&_4);
	 	for(int j=0;j<_4;j++){
	 		scanf("%d",&_5);//scanf 未加& 
			 jm.push_back(_5);
			 num.insert(_5);
		 }
		 int len=0;
		 dfs(len);
		 if(len==inf||num.size()<n){
		 	if(len==inf)
		 	printf("Path %d: NA (Not a TS cycle)\n",i);
		 	//忘了写下一段
			 else 
			 printf("Path %d: %d (Not a TS cycle)\n",i,len) ;
		 }else if(jm[0]!=jm[jm.size()-1]){
		 printf("Path %d: %d (Not a TS cycle)\n",i,len);
		 }else if(_4>n+1){
		 	printf("Path %d: %d (TS cycle)\n",i,len);
		 	if(len<min){
		 		min=len;
		 		minindex=i;
			 }
		 }else if(_4==n+1){
		 	printf("Path %d: %d (TS simple cycle)\n",i,len);
		 		if(len<min){
		 		min=len;
		 		minindex=i;
			 }
		 }
		 
	 }
	 printf("Shortest Dist(%d) = %d",minindex,min);
	 return 0;
	 
 }
//1146
#include<bits/stdc++.h>
 using namespace std;
 vector<int> lin[1009];
 vector<int> book(1009) ,temp(1009) ;
 int main(){
 	int n,m,_1,_2;
 	scanf("%d%d",&n,&m);
 	for(int i=0;i<m;i++){
 		scanf("%d%d",&_1,&_2);
 		lin[_1].push_back(_2);
 		book[_2]++;//对通用变量进行修改导致重复query后面出错 
	 }
	 int k,_3,yu=0;
	 scanf("%d",&k);
	 for(int i=0;i<k;i++){
	 	int flag=1;
	 	temp=book;//引参 
		 for(int j=1;j<=n;j++){//1--n
	 	scanf("%d",&_3);
		 if(temp[_3]!=0){
		 	flag=0;
		 }
		 if(flag==1){
		 	for(int q=0;q<lin[_3].size();q++){
		 		temp[lin[_3][q]]--;
			 }
		 }	
		 }
      if(flag==1) continue;
      else{
	    if(yu!=0) printf(" ");//这么写的前提是最后一次必须输出不可能 
	    	printf("%d",i);
	    	yu=1;//最好是让第一次不输出空格后面都输出 
	  }
	 }
	return 0; 
 }
//1142
#include<bits/stdc++.h>
 using namespace std;
 int book[250],a[250][250];
 int main(){
 	int n,m,_1,_2;
 	scanf("%d%d",&n,&m);
 	for(int i=0;i<m;i++){
 		scanf("%d%d",&_1,&_2);
 		a[_1][_2]=a[_2][_1]=1;
	 }
	 int k,_3,_4;
	 scanf("%d",&k);
	 for(int i=0;i<k;i++){
	 	scanf("%d",&_3);
	 	vector<int> temp;
	 	fill(book,book+250,0);
	 	for(int j=0;j<_3;j++){
	 		scanf("%d",&_4);
			 temp.push_back(_4);
			 book[_4]=1;
		 }   int cli=1;
		    for(int a1=0;a1<_3;a1++){
		 	for(int a2=a1+1;a2<_3;a2++){
		 		if(a[temp[a1]][temp[a2]]==0){//如果上面有量没用看看是不是落了双索引 
		 			cli=0;
		 			break;
				 }
			 }
		   }
			 if(cli==0){
			 	printf("Not a Clique\n");
			 }else{ int maxcli=1;
			 	for(int i=1;i<=n;i++){
			 		if(book[i]==0){
			 			int j;
			 			for( j=0;j<temp.size();j++){
			 				if(a[i][temp[j]]==0){
			 					break;
							 }
						 }
						 if(j==temp.size()){//应该放在整个for循环外 因为我们的结束标志仅仅是最后他停在那里而不是循环一个弄一个 
							 	maxcli=0;
							 }
					 }
				 }
				 if(maxcli==0){
				 	printf("Not Maximal\n");
				 }else{
				 	printf("Yes\n");
				 }
			 }
		 }
		 return 0;
}
 
//1131
#include<bits/stdc++.h>
using namespace std;
 map<int,int>xmindex;
 int hi(vector<int>temp){//temp为存储的线路 
 	int cnt=0;
	 for(int i=1;i<temp.size()-1;i++){//相当于边有标记 
 		if(xmindex[10000*temp[i]+temp[i-1]]!=xmindex[10000*temp[i+1]+temp[i]]){
 			cnt++;//换乘次数 
		 }
	 }
	 return cnt;
 }
 vector<int>tempp,ans,a[10000];
int minn=1000000,minhi=1000000;//所有在外面并且可能用到的都要crt 注意常数的crt 尤其是被赋值的变量 
 int visit[10000],endd;//终点已声明 
 void dfs(int qq){
 	//end
 	if(qq==endd){
 		visit[qq]=1;
 		tempp.push_back(qq);
 		if(tempp.size()<minn){//不适合用bfs因为bfs是一大片一大片有一个统一的度量所以可以求最短路,但是没有记录每一条特定线的前后关系,所以只适合于单标准,像这里就不能统计换乘次数 
 			minn=tempp.size();
 			minhi=hi(tempp);
 			ans=tempp;
		 }else if(tempp.size()==minn){
		 	if(hi(tempp)<minhi){
			 ans=tempp;
			 minhi=hi(tempp);
			 }
			 } 
		  
		 tempp.pop_back();
		 return;
	   
	 }
 	tempp.push_back(qq);//doesn's name a type 层次错误 
 	visit[qq]=1;
 	for(int i=0;i<a[qq].size();i++){//此时只能用for循环来卡 
 		if(visit[a[qq][i]]==0){
 			dfs(a[qq][i]);//需要解封有环且无向图
			 visit[a[qq][i]]=0;//解封 
		 }
	 }
	 tempp.pop_back();
 }
 int main(){
 	int n,_1,_2;
 	scanf("%d",&n);
 	vector<int> temp1[n+1];
 	for(int i=1;i<=n;i++){
 		scanf("%d",&_1);
		 for(int j=0;j<_1;j++){
		 	scanf("%d",&_2);
		 	temp1[i].push_back(_2); 
		 }
	 }
	 for(int i=1;i<=n;i++){
	 	for(int j=1;j<temp1[i].size();j++){
	 		a[temp1[i][j]].push_back(temp1[i][j-1]);
	 		a[temp1[i][j-1]].push_back(temp1[i][j]);
	 		xmindex[10000*temp1[i][j]+temp1[i][j-1]]=i;
	 		xmindex[temp1[i][j]+10000*temp1[i][j-1]]=i;
		 }
	 }
	int k,_3;
	scanf("%d",&k);
	for(int i=0;i<k;i++){
		scanf("%d%d",&_3,&endd);
		fill(visit,visit+10000,0);
		tempp.clear();
		ans.clear();
		minn=1000000;minhi=1000000;
		dfs(_3);
		int pre;
		printf("%d\n",ans.size()-1);
		pre=_3;
		for(int i=1;i<ans.size()-1;i++){//相当于边有标记 
 		if(xmindex[10000*ans[i]+ans[i-1]]!=xmindex[10000*ans[i+1]+ans[i]]){
 			printf("Take Line#%d from %04d to %04d.\n",xmindex[10000*ans[i]+ans[i-1]],pre,ans[i]); 
		    pre=ans[i];
		 }
	 }
	 printf("Take Line#%d from %04d to %04d.\n",xmindex[endd*10000+ans[ans.size()-2]],pre,endd); //有可能不转站pre就一直是起点 map记得是相邻边其他的会返回0 
		
	}
	return 0;
 }

 

 总结

1111第一道题两次dijkstra+dfs不知道那个测试点为啥有问题

1131 挺经典的,耗时比较多,dfs需要去标记,因为有环,注意赋值的crt

中间几个题题干中有时候隐藏起来但是需要验证的是此图的连通性

以及修改了通用变量的错误

小细节见上面的注释

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值