[c]代码库
/*
2013腾讯马拉松初赛第2场
1005 湫湫系列故事——设计风景线
________________________________________
Time Limit: 3 Seconds Memory Limit: 65536K
________________________________________
随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好。
现在已经勘探确定了n个位置可以用来建设,在它们之间也勘探确定了m条可以设计的路线以及他们的长度。请问是否能够建成环形的风景线?如果不能,风景线最长能够达到多少?
其中,可以兴建的路线均是双向的,他们之间的长度均大于0。
Input
测试数据有多组,每组测试数据的第一行有两个数字n, m,其含义参见题目描述;
接下去m行,每行3个数字u v w,分别代表这条线路的起点,终点和长度。
[Technical Specification]
1. n<=100000
2. m <= 1000000
3. 1<= u, v <= n
4. w <= 1000
Output
对于每组测试数据,如果能够建成环形(并不需要连接上去全部的风景点),那么输出YES,否则输出最长的长度,每组数据输出一行。
Sample Input
3 3
1 2 1
2 3 1
3 1 1
Sample Output
YES
*/
/*
解题报告:
首先做这题的时候很纠结,不知道题目中说的环形是什么,是要所有的路都用上还是怎么样。经过一番思考后,觉得应该是判环。
我就直接想到了双联通分量了。至于最长路,就是如果不存在双联通分量的情况,必然是几棵树了。就是求一下树的直径。
经过一番YY之后,就开始写了。
先求双联通,然后再BFS,求树直径。交上去之后RE掉了,当时也不确定自己算法正确性,有想过要用加栈的方法。可是没去试。后来和别人讨论了,他让我加了,结果就这么过了。
我看到别人的代码这么短的。
我看了别人的做法原来他们是用并查集来判环的。学习了。
PS:以后递归溢出要加#pragma comment(linker, "/STACK:36777216")//开大点
栈这个试试。
*/
#include<string.h>
#include<map>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#pragma comment(linker, "/STACK:36777216")//开大点栈
using namespace std;
const int MAX = 1100000 * 2;
const double EPS = 1.0e-8;
bool dblcmp(double x) {
if(fabs(x) < EPS)return 0;
return x < 0 ? -1 : 1;
}
const int MAXN = 110000;
const int MAXM = 1100000 * 2;
struct EDGE {
int v, next, d;
} edge[MAXM];
int E;
int com[MAXN], DN, CN, h[MAXN], d[MAXN], stk[MAXN], top;
int head[MAXN];
void DFS(int t, int f) {
int i, ed;
stk[top++] = t;
d[t] = DN--;
h[t] = d[t];
for(i = head[t]; i != -1; i = edge[i].next) {
ed = edge[i].v;
if(ed != f) {
if(d[ed] == 0) {
DFS(ed, t);
if(h[ed] > h[t]) h[t] = h[ed];
}
if(com[ed] == 0 && h[t] < d[ed])
h[t] = d[ed];
}
}
if(h[t] == d[t]) {
com[t] = ++CN;
while(stk[top - 1] != t) {
com[stk[top - 1]] = CN;
top--;
}
top--;
}
}
void SCC(int N) {
int i;
CN = 0;
DN = N;
top = 0;
memset(com, 0, sizeof(int) * (N + 2));
memset(h, 0, sizeof(int) * (N + 2));
memset(d, 0, sizeof(int) * (N + 2));
for(i = 1; i <= N; i++) {
if(com[i] == 0)
DFS(i, -1);
}
}
void add(int s, int t, int d) {
edge[E].v = t;
edge[E].d = d;
edge[E].next = head[s];
head[s] = E++;
}
typedef __int64 lld;
int vis[MAXN];
int q[MAXN];
int dis[MAXN];
map<lld, int>mp;
int BFS(int s, int CS, int &ans) {
int rear = 0, front = -1;
int i, v;
dis[s] = 0;
vis[s] = CS;
q[0] = s;
while(rear != front) {
front++;
s = q[front];
for(i = head[s]; i != -1; i = edge[i].next) {
v = edge[i].v;
if(vis[v] == CS)continue;
dis[v] = edge[i].d + dis[s];
vis[v] = CS;
rear++;
q[rear] = v;
}
}
int ind = s;
int tmp = dis[s];
for(i = 1; i <= rear; i++) {
v = q[i];
if(dis[v] > tmp) {
tmp = dis[v];
ind = v;
}
}
if(tmp > ans)ans = tmp;
return ind;
}
bool dig(char x) {
return x >= '0' && x <= '9';
}
int getval() {
int ret = 0, sign = 1;
char c;
while(!dig(c = getchar()) && c != '-');
if(c == '-')sign = -1;
else ret = c - '0';
while(dig(c = getchar()))ret = ret * 10 + c - '0';
return ret * sign;
}
int main() {
int i, n, m, j;
int k, CS = 1;
while(scanf("%d%d", &n, &m) != EOF) {
//mp.clear();
memset(head, -1, sizeof(int) * (n + 5));
E = 0;
bool flag = false;
while(m--) {
//scanf("%d%d%d",&i,&j,&k);
i = getval();
j = getval();
k = getval();
if(i == j)continue; //
//if(i>j)swap(i,j);
//lld tmp=(lld)(i)*(lld)(1000000)+(lld)(j);
//mp[tmp]++;
//if(mp[tmp]>1)flag=true;
add(i, j, k);
add(j, i, k);
}
if(flag) {
puts("YES");
continue;
}
CS++;
SCC(n);
//printf("CN=%d\n",CN);
if(CN != n) {
puts("YES");
continue;
}
memset(vis, -1, sizeof(int) * (n + 2));
int ans = 0;
int tmp, j;
for(i = 1; i <= n; i++) {
if(vis[i] == -1) {
j = BFS(i, CS, ans);
CS++;
j = BFS(j, CS, ans);
CS++;
}
}
printf("%d\n", ans);
}
return 0;
}