CF 1051F The Shortest Statement

要求每两个点间的最短路,乍一看卧槽这怎么搞!

乱搞。

注意到m<=n+20,很显然要扯到生成树上。

造一棵树,再将非树边加进来(这咋加啊)

以每条非树边的端点为起点跑最短路,统计答案时取树上和非树上的最短距离就好

  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 int n,m,cnt,tot,q,id;
  7 int head[100005];
  8 int dep[100005];
  9 int fa[100005];
 10 int la[100005];
 11 long long dis[100005];
 12 int grand[100005];
 13 int son[100005];
 14 long long ans[100005];
 15 bool mrk[200005];
 16 int siz[100005];
 17 bool usd[100005];
 18 bool vis[100005];
 19 long long len[45][100005];
 20 int findfa(int x){
 21     if(fa[x]==x)return x;
 22     return fa[x]=findfa(fa[x]);
 23 }
 24 struct Query{
 25     int u;
 26     int v;
 27 }qry[100005];
 28 struct Edge{
 29     int fr;
 30     int to;
 31     int val;
 32     int nxt;
 33 }edge[210005];
 34 struct node{
 35     int u;
 36     long long w;
 37     node(int u,long long w):u(u),w(w){}
 38 };
 39 bool operator<(node a,node b){
 40     return a.w>b.w;
 41 }
 42 void init(){
 43     memset(head,-1,sizeof(head));
 44     memset(len,0x3f,sizeof(len));
 45 }
 46 void buildtree(){
 47     for(int i=1;i<=cnt;i+=2){
 48         int u=edge[i].fr;
 49         int v=edge[i].to;
 50         int fu=findfa(u);
 51         int fv=findfa(v);
 52         if(fu==fv)continue;
 53         fa[fv]=fu;
 54         tot++;mrk[i]=mrk[i+1]=true;
 55         if(tot==n-1)return;
 56     }
 57 }
 58 void addedge(int u,int v,int w){
 59     cnt++;
 60     edge[cnt].fr=u;
 61     edge[cnt].to=v;
 62     edge[cnt].val=w;
 63     edge[cnt].nxt=head[u];
 64     head[u]=cnt;
 65 }
 66 void dfs1(int u){
 67     siz[u]=1;son[u]=0;
 68     for(int i=head[u];i!=-1;i=edge[i].nxt){
 69         if(!mrk[i])continue;
 70         int v=edge[i].to;
 71         if(v==la[u])continue;
 72         la[v]=u;dep[v]=dep[u]+1;
 73         dis[v]=dis[u]+edge[i].val;
 74         dfs1(v);
 75         siz[u]+=siz[v];
 76         if(siz[v]>siz[son[u]])son[u]=v;
 77     }
 78 }
 79 void dfs2(int u){
 80     if(son[la[u]]!=u)grand[u]=u;
 81     else grand[u]=grand[la[u]];
 82     for(int i=head[u];i!=-1;i=edge[i].nxt){
 83         if(!mrk[i])continue;
 84         int v=edge[i].to;
 85         if(v==la[u])continue;
 86         dfs2(v);
 87     }
 88 }
 89 int lca(int u,int v){
 90     while(grand[u]!=grand[v]){
 91         if(dep[grand[u]]<dep[grand[v]]){
 92             swap(u,v);
 93         }
 94         u=la[grand[u]];
 95     }
 96     if(dep[u]>dep[v])swap(u,v);
 97     return u;
 98 }
 99 void dijk(int u){
100     id++;len[id][u]=0;
101     memset(vis,0,sizeof(vis));
102     priority_queue<node>que;
103     que.push(node(u,0));
104     while(!que.empty()){
105         node s=que.top();
106         que.pop();
107         if(vis[s.u])continue;
108         vis[s.u]=true;
109         for(int i=head[s.u];i!=-1;i=edge[i].nxt){
110             int v=edge[i].to;
111             if(len[id][v]>len[id][s.u]+edge[i].val){
112                 len[id][v]=len[id][s.u]+edge[i].val;
113                 que.push(node(v,len[id][v]));
114             }
115         }
116     }
117 }
118 int main(){
119     init();
120     scanf("%d%d",&n,&m);
121     for(int i=1;i<=n;i++){
122         fa[i]=i;
123     }
124     for(int i=1;i<=m;i++){
125         int u,v,w;
126         scanf("%d%d%d",&u,&v,&w);
127         addedge(u,v,w);
128         addedge(v,u,w);
129     }
130     buildtree();
131     for(int i=1;i<=cnt;i+=2){
132         int u=edge[i].fr;
133         int v=edge[i].to;
134         if(!mrk[i]){
135             if(!usd[u]){
136                 dijk(u);
137                 usd[u]=true;
138             }
139             if(!usd[v]){
140                 dijk(v);
141                 usd[v]=true;
142             }
143         }
144     }
145     dis[1]=0;dep[1]=1;
146     dfs1(1);dfs2(1);
147     scanf("%d",&q);
148     for(int i=1;i<=q;i++){
149         scanf("%d%d",&qry[i].u,&qry[i].v);
150         int f=lca(qry[i].u,qry[i].v);
151         ans[i]=dis[qry[i].u]+dis[qry[i].v]-dis[f]*2;
152         for(int j=1;j<=id;j++){
153             ans[i]=min(ans[i],len[j][qry[i].u]+len[j][qry[i].v]);
154         }
155     }
156     for(int i=1;i<=q;i++){
157         printf("%lld\n",ans[i]);
158     }
159     return 0;
160 }

 

posted @ 2018-10-29 22:48  Mr_Handsome  阅读(94)  评论(0编辑  收藏  举报