调了2天了,人都裂了,有没有大佬能帮帮我...
查看原帖
调了2天了,人都裂了,有没有大佬能帮帮我...
37322
stephen→_→楼主2020/11/29 13:04
#include <bits/stdc++.h>

using namespace std;

vector <int> G[10005];//vector邻接表存图
int f[5005],q=0,vis[5005],x,y,n,m,ux,uy,a[5005],flag=0,loop_num[5005],p = 0;
void dfs(int x){//m==n-1的情况,因为我后面把vecotr排了序,所以dfs第一遍跑出来的就是最优解
	f[++q] = x;
	for(int i = 0; i < G[x].size(); ++i)
		if(!vis[G[x][i]]) {
			int y = G[x][i];
			vis[y] = 1;
			dfs(y);
		}
}
void find_loop(int x,int root,int fa){//找出在环内的点
	loop_num[++p] = x;
	if(flag) return;
	for(int i = 0; i < G[x].size(); ++i){
		int y = G[x][i];
		if(y==fa) continue;
		if(vis[y]&&y==root) {
			flag = 1;
			return;
		}
		if(!vis[y]){
			vis[y] = 1;
			find_loop(y,root,x);
			vis[y] = 0;
			if(flag) return;
		}
	}
	if(!flag) p--;
}
void dfs1(int x){//情况二,就是枚举删掉环内的边来找到删完边后的当前最优解
	a[++q] = x;
	//printf("%d %d ",a[q],x);
	for(int i = 0; i < G[x].size(); ++i){
		int y = G[x][i];
		if((x==ux&&y==uy)||(x==uy&&y==ux)) continue;
		if(!vis[y]){
			vis[y] = 1;
			dfs(y);
			//printf("%d ",y);
		}
	}
}
void choseans(){//拿当前最优解和已知最优解比较大小,更新
	int bj = 0;
	for(int i = 1; i <= n; ++i){
		if(a[i] < f[i]) {
			bj = 1;
			break;
		}else if(a[i]>f[i]) break;
	}
	if(bj) 
	for(int i = 1; i <= n; ++i){
		f[i] = a[i];
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= m; ++i){
		scanf("%d%d",&x,&y);
		G[x].push_back(y);
		G[y].push_back(x);
	}//无向边存图
	for(int i = 1; i <= n; ++i)//vector排序
		sort(G[i].begin(),G[i].end());
		vis[1] = 1;
		dfs(1);//先跑一遍找出可行解,使f数组有值可比较
	if(m==n-1){//这种情况的话那这个可行解就是最优解
		for(int i = 1; i <= n; ++i) printf("%d ",f[i]); 
	}else if(m==n){
		flag = 0;//flag=1表示已找到环
        //找出环内点
		for(int i = 1; i <= n; ++i){//1到n个点尝试把每个点都作为环的起点(或者根节点)开始跑树
			memset(vis,0,sizeof(vis));//清零				vis[i] = 1;
			if(!flag) {
				p = 0;
				find_loop(i,i,-1);//分别代入当前点,起点,当前点的父节点(无向图的起点无父节点所以代-1进去)。
			}
		}//上面得出一个长度为p的数组loop_num[],里面存的就是在环内的点
		for(int i = 1; i <= p; ++i)
			for(int j = 0;j < G[loop_num[i]].size(); ++j){//枚举删掉环内的边
				memset(vis,0,sizeof(vis));
				q = 0;
				vis[1] = 1;
				ux = loop_num[i];uy = G[i][j];//需要删的边所连接的两个点
				dfs1(1);
				if(q==n) choseans();//如果q=n就寻找更优解
			}
		for(int i = 1; i <= n; ++i) printf("%d ",f[i]);
	}
	return 0;
}

这份代码我自认为写的没有什么太大问题但是样例都过不了,调了2天了,人都裂开了,有没有大佬能帮帮我!

2020/11/29 13:04
加载中...