[bzoj 2725] 故乡的梦
2016-02-04 16:19
375 查看
丧病图论题……
这是个权限题……所以不放传送门了,说一下题目大意。
给定一个n个点,m条边的无向图,一个S,一个T,有Q个询问,每次询问删掉某条边之后S到T的最短路。(n,m,q<=200000)
先从S跑一遍最短路,再从T跑一遍最短路。然后我们考虑一个简化的问题:求删掉某条边之后S到T的最短路是否会变化。
可以看出,满足disS[u]+w(u,v)+disT[v]==disS[T]的边(u,v)一定在S到T的最短路上。我们把所有这样的边弄出来,跑一遍tarjan,那么当且仅当它是桥时S到T的最短路会变化。
这给我们提供了思路。于是,可以将这些tarjan跑出来的双连通分量缩起来。显然,这些双连通分量从S到T构成一条链,将它由S到T的顺序编号。
考虑删掉桥之后的答案,显然是用某一条非最短路上的边(u,v)代替,距离变成disS[u]+w(u,v)+disT[v]。
再考虑每条边可以代替哪些桥。
必须满足一下几个条件:
假设当前这座桥连接i到i+1的连通分量,当前边为(u,v)
1.可以用前i块连通分量的点走到u,且保证是S到u的最短路
2.可以用i之后连通分量的点走到v,且保证是T到v的最短路
于是,我们再跑两棵最短路树,一棵起点为S,另外一棵起点为T,然后给每个点一个belong1[i],一个belong2[i],即从哪个连通分量可以走S到i的最短路到i,从哪个连通分量可以走T到i的最短路到i。然而这样的连通分量可能有很多个,对于belong1,我们选编号最小的;对于belong2,我们选编号最大的。
我们从S到T的每个双连通分量扫描,每扫描到一块,加入这个连通分量到后面的边,删除前面的连通分量到它的边。用一个堆维护,关键字是disS[u]+w(u,v)+disT[v]。起点的连通分量为belong1[i],终点为belong2[i]。
啥都不说上代码。写得快哭了,用map还被卡常了……。
这是个权限题……所以不放传送门了,说一下题目大意。
给定一个n个点,m条边的无向图,一个S,一个T,有Q个询问,每次询问删掉某条边之后S到T的最短路。(n,m,q<=200000)
先从S跑一遍最短路,再从T跑一遍最短路。然后我们考虑一个简化的问题:求删掉某条边之后S到T的最短路是否会变化。
可以看出,满足disS[u]+w(u,v)+disT[v]==disS[T]的边(u,v)一定在S到T的最短路上。我们把所有这样的边弄出来,跑一遍tarjan,那么当且仅当它是桥时S到T的最短路会变化。
这给我们提供了思路。于是,可以将这些tarjan跑出来的双连通分量缩起来。显然,这些双连通分量从S到T构成一条链,将它由S到T的顺序编号。
考虑删掉桥之后的答案,显然是用某一条非最短路上的边(u,v)代替,距离变成disS[u]+w(u,v)+disT[v]。
再考虑每条边可以代替哪些桥。
必须满足一下几个条件:
假设当前这座桥连接i到i+1的连通分量,当前边为(u,v)
1.可以用前i块连通分量的点走到u,且保证是S到u的最短路
2.可以用i之后连通分量的点走到v,且保证是T到v的最短路
于是,我们再跑两棵最短路树,一棵起点为S,另外一棵起点为T,然后给每个点一个belong1[i],一个belong2[i],即从哪个连通分量可以走S到i的最短路到i,从哪个连通分量可以走T到i的最短路到i。然而这样的连通分量可能有很多个,对于belong1,我们选编号最小的;对于belong2,我们选编号最大的。
我们从S到T的每个双连通分量扫描,每扫描到一块,加入这个连通分量到后面的边,删除前面的连通分量到它的边。用一个堆维护,关键字是disS[u]+w(u,v)+disT[v]。起点的连通分量为belong1[i],终点为belong2[i]。
啥都不说上代码。写得快哭了,用map还被卡常了……。
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <cstdlib> #include <algorithm> #include <vector> #include <deque> #include <queue> #include <map> #include <set> #include <ctime> using namespace std; typedef long long ll; const int Maxn=200005; const ll INF=ll(1)<<ll(60); vector<int> bcc[Maxn]; int belong[Maxn],tt; struct node { int x;ll val; node(){} node(int _x,ll _val) { x=_x,val=_val; } }; bool operator < (const node &a,const node &b) { return a.val>b.val; } priority_queue<node> H; struct Edge { int from,to,cost;bool flag; }E[Maxn<<1]; bool cmp(const Edge &a,const Edge &b) { return belong[a.from]<belong[b.from]; } int Get() { char ch; int v=0; bool f=false; while (!isdigit(ch=getchar())) if (ch=='-') f=true; v=ch-48; while (isdigit(ch=getchar())) v=v*10+ch-48; if (f) return -v;else return v; } void Put(ll x) { char ch[21]; int tot=0; if (x==0) { puts("0");return; } while (x) ch[++tot]=x%10,x/=10; for (;tot;tot--) putchar(ch[tot]+48);puts(""); } int n,m,q,tot,S,T,fst[Maxn],pre[Maxn<<1],to[Maxn<<1],from[Maxn<<1],cost[Maxn<<1],head,tail,Q[Maxn], dfs_clock,dfn[Maxn],low[Maxn],col[Maxn],bridge[Maxn],belong2[Maxn]; ll disS[Maxn],disT[Maxn],ans[Maxn<<1]; bool vis[Maxn],flag[Maxn<<1],imp[Maxn<<1],imp2[Maxn<<1],is_bridge[Maxn<<1]; void add(int x,int y,int c) { if (x==y) return; pre[++tot]=fst[x],fst[x]=tot,from[tot]=x,to[tot]=y,cost[tot]=c; E[tot].from=x,E[tot].to=y,E[tot].cost=c,E[tot].flag=false; pre[++tot]=fst[y],fst[y]=tot,from[tot]=y,to[tot]=x,cost[tot]=c; E[tot].from=y,E[tot].to=x,E[tot].cost=c,E[tot].flag=false; } void Dijkstra(int S,ll *dis) { while (!H.empty()) H.pop(); for (int i=1;i<=n;i++) vis[i]=false,dis[i]=INF; dis[S]=0; H.push(node(S,0)); vis[S]=true; while (!H.empty()) { node cur=H.top(); H.pop(); int x=cur.x; if (cur.val!=dis[x]) continue; for (int i=fst[x];i;i=pre[i]) { int y=to[i]; if (!vis[y] && dis[x]+ll(cost[i])<dis[y]) dis[y]=dis[x]+ll(cost[i]),H.push(node(y,dis[y])); } vis[x]=true; } } void tarjan(int x,int prev) { vis[x]=true; dfn[x]=low[x]=++dfs_clock; for (int i=fst[x];i;i=pre[i]) { int y=to[i]; if (i==(prev^1) || !flag[i]) continue; if (!vis[y]) tarjan(y,i),low[x]=min(low[x],low[y]); else low[x]=min(low[x],dfn[y]); } if (dfn[x]==low[x]) is_bridge[prev]=is_bridge[prev^1]=true; } void dfs(int x) { belong[x]=tot,vis[x]=true; bcc[tot].push_back(x); for (int i=fst[x];i;i=pre[i]) { int y=to[i]; if (!vis[y] && !is_bridge[i] && flag[i]) dfs(y); } } void getchain() { for (int i=1;i<=tot;i++) vis[i]=false; int cur=belong[S],cnt=0; while (cur!=belong[T]) { col[cur]=++cnt;vis[cur]=true; int len=bcc[cur].size(); bool ff=false; for (int i=0;i<len && !ff;i++) { int x=bcc[cur][i]; for (int j=fst[x];j && !ff;j=pre[j]) if (is_bridge[j] && !vis[belong[to[j]]]) { bridge[cnt]=j; cur=belong[to[j]]; ff=true; } } } col[cur]=++cnt; for (int i=1;i<=n;i++) belong[i]=col[belong[i]],belong2[i]=belong[i]; for (int i=1;i<=tot;i++) while (!bcc[i].empty()) bcc[i].pop_back(); tot=cnt; for (int i=1;i<=n;i++) bcc[belong[i]].push_back(i); } void bfs1(int cur) { head=tail=1; int len=bcc[cur].size(); for (int i=0;i<len;i++) Q[tail++]=bcc[cur][i],vis[bcc[cur][i]]=true; while (head!=tail) { int x=Q[head++]; for (int i=fst[x];i;i=pre[i]) { int y=to[i]; if (!vis[y] && imp[i]) Q[tail++]=y,belong[y]=cur,vis[y]=true; } } } void bfs2(int cur) { head=tail=1; int len=bcc[cur].size(); for (int i=0;i<len;i++) Q[tail++]=bcc[cur][i],vis[bcc[cur][i]]=true; while (head!=tail) { int x=Q[head++]; for (int i=fst[x];i;i=pre[i]) { int y=to[i]; if (!vis[y] && imp2[i]) Q[tail++]=y,belong2[y]=cur,vis[y]=true; } } } void init() { n=Get(),m=Get(); int x,y,c; tot=1; for (int i=1;i<=m;i++) x=Get(),y=Get(),c=Get(),add(x,y,c); S=Get(),T=Get(); tt=tot; Dijkstra(S,disS); Dijkstra(T,disT); if (disS[T]==INF) { q=Get(); while (q--) x=Get(),y=Get(),puts("Infinity"); return; } for (int i=2;i<=tot;i+=2) { if (disS[from[i]]+ll(cost[i])+disT[to[i]]==disS[T] || disS[to[i]]+ll(cost[i])+disT[from[i]]==disS[T]) flag[i]=flag[i^1]=true,E[i].flag=E[i^1].flag=true; else { if (disS[from[i]]+ll(cost[i])==disS[to[i]]) imp[i]=true; if (disT[from[i]]+ll(cost[i])==disT[to[i]]) imp2[i]=true; if (disS[to[i]]+ll(cost[i])==disS[from[i]]) imp[i^1]=true; if (disT[to[i]]+ll(cost[i])==disT[from[i]]) imp2[i^1]=true; } } for (int i=1;i<=n;i++) vis[i]=false; dfs_clock=0; tarjan(S,0); for (int i=1;i<=n;i++) vis[i]=false; tot=0; for (int i=1;i<=n;i++) if (!vis[i]) tot++,dfs(i); getchain(); for (int i=1;i<=n;i++) vis[i]=false; for (int i=1;i<=tot;i++) bfs1(i); for (int i=1;i<=n;i++) vis[i]=false; for (int i=tot;i>=1;i--) bfs2(i); } void work() { if (disS[T]==INF) return; while (!H.empty()) H.pop(); sort(E+2,E+tt+1,cmp); for (int i=1,j=2;i<=tot-1;i++) { for (;j<=tt && belong[E[j].from]==i;j++) if (!E[j].flag) H.push(node(E[j].to,disS[E[j].from]+ll(E[j].cost)+disT[E[j].to])); while (!H.empty() && belong2[H.top().x]<=i) H.pop(); if (!H.empty()) ans[bridge[i]]=ans[bridge[i]^1]=H.top().val; else ans[bridge[i]]=ans[bridge[i]^1]=INF; } for (int i=2;i<=tt;i++) if (!is_bridge[i]) ans[i]=disS[T]; q=Get(); int x,y; while (q--) { x=Get(),y=Get(); ll res; int pos; for (int i=fst[x];i;i=pre[i]) if (to[i]==y) { pos=i;break; } if (x!=y) res=ans[pos];else res=disS[T]; if (res!=INF) Put(res);else puts("Infinity"); } } int main() { // freopen("hometown.in","r",stdin); // freopen("hometown.out","w",stdout); init(); work(); return 0; }
相关文章推荐
- HDU4786(生成树)
- mybaits错误解决:There is no getter for property named 'id' in class 'java.lang.Long'
- 2015百度招聘
- IOS 颜色值#ffffff转UIColor
- Python中的字符串类型基本知识学习教程
- 使用Hadoop分析数据——简单案例java语言编程之MaxTemperature
- I/O流
- 【python 笔记】字符串translate用法
- ___89___GraphicsPath_GDI矩阵变幻Transform
- 对象归档
- 【精】配色达人速成
- 关于iOS中图片的平铺
- 例题6-6 UVs679 Dropping Balls(二叉树)
- Leetcode Path Sum
- %s的用法
- 【Android】3.22 示例22--LBS云检索功能
- jsp相关知识
- 基于Tcp协议与基于Http协议的RPC简介笔记
- 解决pip无法使用http的源
- python 简介