标签:
题目大意:给你一个图,存在一个环,问所有节点到环的最短距离,节点n的个数为3000
思路:组成环的节点的度数大于等于2.。。
因为n只有3000 , 所以可以暴力求出环由哪些节点组成。具体方法就是将节点度数为1的度数减1,与他连接的节点度数减1,直至没有度数为1的节点。那么剩余度数大于等于2的节点就是组成环的节点。接下来只需要从环的每个节点dfs求出每个点的距离即可。
若数据较大时,可以采用一遍搜索确定组成环的节点。具体方法是:首先将度数为1的节点如队列,将与度数为1连接的点的度数减1,若度小于2 的节点进行如队列继续操作并标记访问。最后没有被标记访问的就是组成环的节点。。感觉这样可能跑的更快。。
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <fstream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <iomanip> using namespace std; //#pragma comment(linker, "/STACK:102400000,102400000") #define maxn 5005 #define MOD 1000000007 #define mem(a , b) memset(a , b , sizeof(a)) #define LL long long #define ULL unsigned long long typedef pair<int , int> pii; const long long INF= 0x3fffffff; int n , m; vector<int>v[maxn]; int d[maxn]; int vis[maxn] , vis2[maxn]; int cost[maxn]; void dfs(int root , int dis) { vis2[root] = 1; cost[root] = dis; for(int i = 0 ;i < v[root].size() ; i ++) { if(d[v[root][i]] >= 2|| vis2[v[root][i]]) continue; dfs(v[root][i] , dis + 1); } } int main() { while(scanf("%d" , &n) != EOF) { for(int i = 0 ; i <= n ; i ++) {v[i].clear();cost[i] = INF ;} mem(d , 0); mem(vis , 0); int a , b; for(int i = 0 ; i < n ; i ++) { scanf("%d %d" , &a , &b); v[a].push_back(b); v[b].push_back(a); d[a]++; d[b]++; } //cout << 1 << endl; // cout << d[6] << endl; int flag = 1; while(flag) { flag = 0; for(int i = 1 ; i <= n ; i++) { if(d[i] == 1) { // cout << i << endl; flag = 1; d[i]--; for(int j = 0 ; j < v[i].size() ; j ++) { d[v[i][j]]--; } break; } } } //cout << d[6] << endl; for(int i = 1 ; i <= n ; i ++) { if(d[i] >= 2) { cost[i] = 0;} } for(int i = 1 ; i <= n ;i ++) { if(d[i] >= 2) { mem(vis2 , 0); dfs(i , 0); } } for(int i = 1 ; i <= n ; i ++) { printf("%d" , cost[i]); if(i != n) printf(" "); } printf("\n"); } return 0; }
标签:
原文地址:http://blog.csdn.net/qq_24477135/article/details/51372148