标签:complex problem n+1 read fat map 题目 lex ring
圆方树练习。
首先搞出圆方树(建树)。注意在建树的过程中即Tarjan时要同时记录三个信息:1.环的大小。 2.环上每个点到环顶点的距离。 3.最优距离在那一边。
这些都很容易求出来。然后我们把圆点到方点的边权赋为环到顶点的最短距离,方点到圆点的赋为0。
对于每次询问的两个点,询问在圆方树上的LCA,如果LCA是圆点,直接计算即可。下面分析方点的情况。
如果两点的LCA是方点,那么显然在原仙人掌的环上。
这时候对于这个可以选择两条路径,根据题目显然不能暴力走。
对于仙人掌上的两个点,因为我们已经求出最优距离应该走哪一边,而且我们知道了环的大小,所以相对来时没那么优的一条路径也可以计算出来。
所以如果两个点的最优选择是不同方向的,直接用环的大小减去即可。如果是相同方向的,分别计算,取MIN即可。
//BZOJ2125
//by Cydiater
//2017.2.13
#include <iostream>
#include <queue>
#include <map>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <iomanip>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <bitset>
#include <set>
#include <vector>
#include <complex>
using namespace std;
#define ll long long
#define up(i,j,n) for(int i=j;i<=n;i++)
#define down(i,j,n) for(int i=j;i>=n;i--)
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
#define Auto(i,node) for(int i=LINK[node];i;i=e[i].next)
const int MAXN=1e5+5;
const int oo=0x3f3f3f3f;
inline int read(){
char ch=getchar();int x=0,f=1;
while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int N,M,Q,NN,Girth[MAXN];
vector<int>E[MAXN],W[MAXN];
bool cho[MAXN];
struct Info{
int sx,sy,lca;
};
struct Graph{
int LINK[MAXN],len,dfn[MAXN],low[MAXN],stack[MAXN],top,dfs_clock,dep[MAXN],fa[MAXN][25],dis[MAXN][25];
struct edge{
int y,next,v;
}e[MAXN];
inline void insert(int x,int y,int v){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;e[len].v=v;}
inline void Insert(int x,int y,int v){insert(x,y,v);insert(y,x,v);}
int Col(int id){
int dist=0,siz=E[id].size();
up(i,0,siz-1){
int x=E[id][i],y=E[id][(i+1)%siz];
Auto(j,x)if(e[j].y==y){
dist+=e[j].v;
W[id].push_back(e[j].v);
}
}
return dist;
}
void Tarjan(int node){
dfn[node]=low[node]=++dfs_clock;
stack[++top]=node;
Auto(i,node)if(!dfn[e[i].y]){
Tarjan(e[i].y);
cmin(low[node],low[e[i].y]);
if(low[e[i].y]>=dfn[node]){
NN++;int tmp;
do{
tmp=stack[top--];
E[NN].push_back(tmp);
}while(tmp!=e[i].y);
E[NN].push_back(node);
Girth[NN]=Col(NN);
}
}else cmin(low[node],dfn[e[i].y]);
}
void DFS(int node,int father,int deep){
fa[node][0]=father;dep[node]=deep;
Auto(i,node)if(e[i].y!=father)
DFS(e[i].y,node,deep+1);
if(node>N){
dis[node][0]=0;
int siz=E[node].size(),dist=0;
down(j,siz-2,0){
dist+=W[node][j];
dis[E[node][j]][0]=min(dist,Girth[node]-dist);
if(dis[E[node][j]][0]==dist) cho[E[node][j]]=0;
else cho[E[node][j]]=1;
}
}
}
void Get_Ancestor(){
up(i,1,20)up(node,1,N)if(fa[node][i-1]){
fa[node][i]=fa[fa[node][i-1]][i-1];
dis[node][i]=dis[node][i-1]+dis[fa[node][i-1]][i-1];
}
}
Info LCA(int x,int y){
if(x==y) return (Info){0,0,x};
if(dep[x]<dep[y])swap(x,y);
down(i,20,0)if(dep[x]-(1<<i)>=dep[y])x=fa[x][i];
if(x==y) return (Info){0,0,x};
down(i,20,0)if(fa[x][i]!=0&&fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
return (Info){x,y,fa[x][0]};
}
int Get(int node,int aim){
int ans=0;
down(i,20,0)if(dep[node]-(1<<i)>=dep[aim]){
ans+=dis[node][i];
node=fa[node][i];
}
return ans;
}
}G1,G2;
namespace solution{
void Prepare(){
N=read();M=read();Q=read();
while(M--){
int x=read(),y=read(),v=read();
G1.Insert(x,y,v);
}
NN=N;
G1.Tarjan(1);
up(i,N+1,NN){
int siz=E[i].size();
up(j,0,siz-1)G2.Insert(i,E[i][j],0);
}
G2.DFS(1,0,0);
G2.Get_Ancestor();
//up(i,1,N)cout<<G2.dis[i][0]<<endl;
}
void Solve(){
while(Q--){
int x=read(),y=read(),ans=0;
Info info=G2.LCA(x,y);
int lca=info.lca,sx=info.sx,sy=info.sy;
if(lca>N){
int tmp;
if(cho[sx]^cho[sy]) tmp=G2.dis[sx][0]+G2.dis[sy][0];
else tmp=min(Girth[lca]-G2.dis[sx][0]+G2.dis[sy][0],Girth[lca]-G2.dis[sy][0]+G2.dis[sx][0]);
ans=G2.Get(x,sx)+G2.Get(y,sy)+min(G2.dis[sx][0]+G2.dis[sy][0],Girth[lca]-tmp);
}
else ans=G2.Get(x,lca)+G2.Get(y,lca);
printf("%d\n",ans);
}
}
}
int main(){
using namespace solution;
Prepare();
Solve();
return 0;
}
标签:complex problem n+1 read fat map 题目 lex ring
原文地址:http://www.cnblogs.com/Cydiater/p/6393271.html