Terrorists UVALive
来源:互联网 发布:vba 数组赋值 编辑:程序博客网 时间:2024/06/01 13:04
题目大意:
给一张n个点,m条边的无向图。共有q个询问,每次询问u到v的最短路。
n <= 100000 , n-1 <= m <= n + 50 , q <= 50000
思路:
注意到边的的数量,n和m非常接近,所以可以近似于一棵树,这样,我们先抛出一棵最小生成树出来,然后之后这样肯定会有多出来的边,然后我们把多出来的边的端点都存下来,这样就出来了一些除了树上的点之外的点,这样我们再把这些点跑一边dij,这样之后我们对于查询u,v时不就变成了最小生成树上的距离和枚举每一个树上之外的点的dij的最小值了么,至于树上的最小值,我们可以lca,rmq搞;
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<queue>#include<cmath>using namespace std;#define fuck() cout<<"-----"<<endl#define INF 0x3f3f3f3fconst int maxed=100000+10;struct E{ int v,bef,val;}e[maxed*10][2];struct Node{ int u,val; bool operator < (const Node& n1) const { return val>n1.val; }};int n,m,q,ans,cnt,head[maxed][2],gen[maxed],dp[maxed],cost[maxed],l[100+10],d[100+10][maxed];int f[maxed][20];bool vis[maxed];int main(){ int slove1(int); void add_(int,int,int,int); void slove2(int,int); void slove3(int,int); void slove4(); int slove5(int,int); int N,kcase=0; scanf("%d",&N); while(N--){ cnt=0; ans=1; memset(head,-1,sizeof(head)); memset(vis,false,sizeof(vis)); scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;i++) gen[i]=i; int a,b,c; for(int i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&c); add_(a,b,c,0); add_(b,a,c,0); int x=slove1(a),y=slove1(b); if(x!=y){ add_(a,b,c,1); add_(b,a,c,1); gen[x]=y; } else{ if(!vis[a]){ l[++cnt]=a; vis[a]=true; } if(!vis[b]){ l[++cnt]=b; vis[b]=true; } } } //fuck(); memset(d,INF,sizeof(d)); for(int i=1;i<=cnt;i++) slove2(l[i],i); //fuck(); memset(vis,false,sizeof(vis)); memset(cost,0,sizeof(cost)); for(int i=1;i<=n;i++) gen[i]=i; slove3(1,1); slove4(); printf("Case %d:\n",++kcase); while(q--){ scanf("%d%d",&a,&b); int w=slove5(a,b); //cout<<w<<endl; int answer=cost[a]+cost[b]-2*cost[w]; for(int i=1;i<=cnt;i++) answer=min(answer,d[i][a]+d[i][b]); printf("%d\n",answer); } } return 0;}int slove1(int x){ if(x==gen[x]) return x; return gen[x]=slove1(gen[x]);}void add_(int x,int y,int val,int cur){ e[ans][cur].v=y; e[ans][cur].val=val; e[ans][cur].bef=head[x][cur]; head[x][cur]=ans++;}void slove2(int s,int cur){ d[cur][s]=0; memset(vis,false,sizeof(vis)); queue<Node> pq; pq.push((Node){s,0}); while(!pq.empty()){ //fuck(); Node no=pq.front(); pq.pop(); for(int i=head[no.u][0];i!=-1;i=e[i][0].bef){ int w=d[cur][no.u]+e[i][0].val; if(d[cur][e[i][0].v]>w){ d[cur][e[i][0].v]=w; pq.push((Node){e[i][0].v,w}); } } }}void slove3(int x,int dep){ vis[x]=true; dp[x]=dep; for(int i=head[x][1];i!=-1;i=e[i][1].bef) if(!vis[e[i][1].v]){ gen[e[i][1].v]=x; cost[e[i][1].v]=cost[x]+e[i][1].val; slove3(e[i][1].v,dep+1); }}void slove4(){ memset(f,-1,sizeof(f)); for(int i=1;i<=n;i++) f[i][0]=gen[i]; int len=(int)log2(n); for(int i=1;i<=len;i++) for(int j=1;j<=n;j++){ int r=f[j][i-1]; if(r==-1) continue; f[j][i]=f[r][i-1]; }}int slove5(int x,int y){ if(dp[x]<dp[y]) swap(x,y); int len=(int)log2(n); for(int i=len;i>=0;i--){ int r=f[x][i]; if(r==-1||dp[r]<dp[y]) continue; x=r; } if(x==y) return x; for(int i=len;i>=0;i--){ int r1=f[x][i],r2=f[y][i]; if(r1==r2) continue; x=r1; y=r2; //fuck(); } //cout<<f[x][0]<<endl; return f[x][0];}
阅读全文
0 0
- Terrorists UVALive
- Troops in Iraq Capture Terrorists, Weapons Caches
- SPOJ:Terrorists(LCA + SPFA最短路)
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- 友盟消息推送 3.x.x 的获取不到设备token问题 s=-11,s1=accs bindapp error
- es6详解
- 病毒木马查杀实战第018篇:病毒特征码查杀之基本原理
- springboot之全局异常
- poj3009——Curling 2.0
- Terrorists UVALive
- hdu3829-Cat VS Dog(最大独立集,匹配问题)
- sed
- Vue学习日志:Vue实例(2)
- angularjs中的filter(过滤器)——格式化日期的date
- com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.apache.ibati
- 使用PullToRefresh实现下拉刷新和上拉加载
- Mac小技巧之Sierra系统中安全性与隐私中没有"任何来源"选项
- Gson 解析集合泛型