题目
题解
思路:
自环重边可以特判然后就变成了找树上的直径最大,答案加1即可
否则这就是一棵基环树,找到这个环,然后求出以环上的每个节点为根的最大直径,然后考虑在环上做贡献。
对于环上的每个点,先求出环的总长summ,显然对于i,与它贡献的点j一定满足,sum[i]表示从起点到i的环上路径长,其中起点可以随便给
然后破环成链,因为求的是最大,直接用单调队列维护即可。至于怎样找环,可以使用拓扑排序,也可以直接DFS
注意
拓扑排序不要写错,先判断这个点是否在环上,然后第二次连边时不要脸度数仍为2的边
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int MAXN = 1e6 + 3;
inline char GetChar(){
static char buf[10001],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,10001,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int &n){
short f=1;
long long x=0;
char c=GetChar();
while(isdigit(c)==false){
if(c=='-'){
f=-1;
}
c=GetChar();
}
while(isdigit(c)==true){
x=((x<<3)+(x<<1)+(c^48));
c=GetChar();
}
n=x*f;
}
struct edge{
int v , w;
edge(){}
edge( int V, int W ){
v = V , w = W;
}
};
vector<edge>G[MAXN] , G1[MAXN];
int d[MAXN] , n;
queue<int>q;
ll dp[MAXN][2] , maxx , len[MAXN<<1] , dp1[MAXN<<1];
void dfs( int x , int f , int yuan ){
for( int i = 0 ; i < G1[x].size() ; i ++ ){
int v= G1[x][i].v , w = G1[x][i].w;
if( v == f ) continue;
dfs( v , x , yuan );
if( dp[v][0] + w > dp[x][0] )
dp[x][1] = dp[x][0] , dp[x][0] = dp[v][0] + w;
else if( dp[v][0] + w > dp[x][1] )
dp[x][1] = dp[v][0] + w;
}
maxx = max( maxx , dp[x][1] + dp[x][0] );
}
void dfs2( int x , int f , int yuan ){
for( int i = 0 ; i < G[x].size() ; i ++ ){
int v= G[x][i].v , w = G[x][i].w;
if( v == f ) continue;
dfs2( v , x , yuan );
if( dp[v][0] + w > dp[x][0] )
dp[x][1] = dp[x][0] , dp[x][0] = dp[v][0] + w;
else if( dp[v][0] + w > dp[x][1] )
dp[x][1] = dp[v][0] + w;
}
maxx = max( maxx , dp[x][1] + dp[x][0] );
}
bool vis[MAXN];
int s[MAXN<<1] , ncnt , head , tail , que[MAXN<<1];
int X[MAXN] , Y[MAXN] , W[MAXN];
ll quan;
inline void dfs1( int x , int st , int f ){
s[++ncnt] = x;vis[x] = 1;
for( int i = 0 ; i < G[x].size() ; i ++ ){
int v= G[x][i].v;
if( v == f ) continue;
if( d[v] == 2 && !vis[v] ){
quan += G[x][i].w;
dp1[ncnt+1] = dp[v][0];
len[ncnt+1] = len[ncnt] + G[x][i].w;
dfs1( v , st , x );
}
else if( v == st ){
quan += G[x][i].w;
return ;
}
}
}
int oo[MAXN];
bool cmp( int x , int y ){
if( X[x] ^ X[y] )
return X[x] < X[y];
if( Y[x] ^ Y[y] )
return Y[x] < Y[y];
return W[x] < W[y];
}
int main(){
Read( n );
bool fl = 0;
for( int i = 1 ; i <= n ; i ++ ){
Read( X[i] );Read( Y[i] );Read( W[i] );
if( X[i] > Y[i] ) swap( X[i] , Y[i] );
oo[i] = i;
}
sort( oo + 1 , oo + n + 1 , cmp ) ;
for( int i = 1 ; i <= n ; i ++ ){
if( (X[oo[i]] == X[oo[i-1]] && Y[oo[i]] == Y[oo[i-1]]) || X[oo[i]] == Y[oo[i]] ) { fl = 1; continue;}
int x = X[oo[i]] , y = Y[oo[i]] , w = W[oo[i]];
d[x] ++ , d[y] ++;
G[x].push_back( edge( y , w ) );
G[y].push_back( edge( x , w ) );
}
if( fl ){
dfs2( 1 , 0 , 1 );
printf( "%lld" , maxx + 1 );
return 0;
}
for( int i = 1; i <= n ; i ++ ){
if( d[i] == 1) {
q.push( i );
d[i] --;
}
}
while( !q.empty() ){
int x = q.front();
q.pop();
for( int i = 0 ; i <G[x].size() ; i ++ ){
int v= G[x][i].v;
d[v] --;
if( d[v] == 1 ){
q.push( v );
d[v] --;
}
}
}
for( int i = 1 ; i <= n ; i ++ ){
int x = X[i] , y = Y[i] , w = W[i];
if( d[x] == 2 || d[y] == 2 ) continue;
G1[x].push_back( edge( y , w ) );
G1[y].push_back( edge( x , w ) );
}
for( int i = 1 ; i <= n ; i ++ ){
if( d[i] == 2 ){
for( int j = 0 ; j < G[i].size() ; j ++ ){
int v = G[i][j].v , w = G[i][j].w;
if( d[v] == 2 ) continue;
dfs( v , i , i );
if( dp[v][0] + w > dp[i][0] )
dp[i][1] = dp[i][0] , dp[i][0] = dp[v][0] + w;
else if( dp[v][0] + w > dp[i][1] )
dp[i][1] = dp[v][0] + w;
maxx = max( maxx , dp[i][1] + dp[i][0] );
}
}
}
for( int i = 1 ; i <= n ; i ++ ){
if( d[i] == 2 ){
len[1] = 0;dp1[1] = dp[i][0];
dfs1( i , i , 0 );
break;
}
}
for( int i = 1 ; i <= ncnt ; i ++ ){
len[i+ncnt] = len[i] + quan;
dp1[i+ncnt] = dp1[i];
}
ncnt *= 2;
int last = 1;
head = 1;
for( int i = 2 ; i <= ncnt / 2 ; i ++ ){
if( ( len[i] - len[1] ) * 2 <= quan ){
while( head <= tail && len[que[tail]] + dp1[que[tail]] < len[i] + dp1[i] ) tail --;
que[++tail] = i;
last = i;
}
else break;
}
for( int i = 1 ; i <= ncnt / 2 ; i ++ ){
while( head <= tail && ( (len[que[head]] - len[i] ) * 2 > quan || que[head] == i ) ) head ++;
last = max( last , i );
while( last + 1 <= ncnt && last + 1 != i + ncnt && (len[last+1] - len[i] ) * 2 <= quan ){
while( head <= tail && dp1[last+1] + len[last+1] > dp1[que[tail]] + len[que[tail]] ) tail --;
que[++tail] = last + 1;last ++;
}
if( head <= tail )
maxx = max( maxx , dp1[i] + dp1[que[head]] + len[que[head]] - len[i] );
}
printf( "%lld" , maxx + 1 );
return 0;
}
冗长无比...