1. 程式人生 > >BZOJ2200: [Usaco2011 Jan]道路和航線

BZOJ2200: [Usaco2011 Jan]道路和航線

pop www. usaco print per isp head dijkstra pre

n<=25000個點m1<=50000條正權無向邊m2<=50000條正負權有向邊,保證有向邊連接的無向邊聯通塊形成一個拓撲圖,求從s到每個點最短路。

第一次發現不會最短路。沒看題亂寫迪傑無腦WA,很好。迪傑從來不能處理負權最短路,然後就開始啃題解。。http://www.cnblogs.com/staginner/archive/2012/10/01/2709487.html這篇代碼不錯,講得也很好。

在每個無向邊聯通塊中找最短路可以直接迪傑。至於過度到不同的聯通塊,可以對無向圖聯通塊形成的拓撲圖按拓撲序來走。也就是說開一個隊列記待搜集和每個集合在從前搜到的起點,在每次迪傑時利用並更新他們。

過程有點長,需組織完整後一氣呵成!

技術分享
  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<algorithm>
  4 #include<math.h>
  5 //#include<iostream>
  6 #include<queue>
  7 using namespace std;
  8 
  9 int n,m1,m2,s;
 10 #define maxn 25011
 11 #define maxm 100011
 12 const int inf=0x3f3f3f3f;
 13 struct
Edge{int to,next,v;}; 14 struct qnode 15 { 16 int v,id; 17 bool operator < (const qnode &b) const {return v<b.v;} 18 bool operator > (const qnode &b) const {return v>b.v;} 19 }; 20 int ufs[maxn]; 21 void ufsclear(int n) 22 { 23 for (int i=1;i<=n;i++) ufs[i]=i;
24 } 25 int find(int x) {return x==ufs[x]?x:(ufs[x]=find(ufs[x]));} 26 void Union(int x,int y) 27 { 28 x=find(x),y=find(y); 29 if (x==y) return; 30 ufs[x]=y; 31 } 32 struct Graph 33 { 34 Edge road[maxm],fly[maxm]; 35 int froad[maxn],ffly[maxn],lr,lf; 36 Graph() 37 { 38 memset(froad,0,sizeof(froad)); 39 memset(ffly,0,sizeof(ffly)); 40 lr=lf=2; 41 } 42 void in(Edge *edge,int *first,int &le,int x,int y,int v) 43 { 44 Edge &e=edge[le]; 45 e.to=y;e.v=v; 46 e.next=first[x]; 47 first[x]=le++; 48 } 49 void insert(Edge *edge,int *first,int &le,int x,int y,int v) 50 { 51 in(edge,first,le,x,y,v); 52 in(edge,first,le,y,x,v); 53 } 54 void in(int x,int y,int v) {in(fly,ffly,lf,x,y,v);} 55 void insert(int x,int y,int v) {insert(road,froad,lr,x,y,v);} 56 int deg[maxn]; 57 int que[maxn],head,tail;bool vis[maxn]; 58 void bfs() 59 { 60 que[head=(tail=1)-1]=s; 61 vis[s]=1; 62 memset(deg,0,sizeof(deg)); 63 while (head!=tail) 64 { 65 const int now=que[head++]; 66 for (int i=froad[now];i;i=road[i].next) 67 { 68 Edge &e=road[i]; 69 if (!vis[e.to]) vis[e.to]=1,que[tail++]=e.to; 70 } 71 for (int i=ffly[now];i;i=fly[i].next) 72 { 73 Edge &e=fly[i]; 74 deg[find(e.to)]++; 75 if (!vis[e.to]) vis[e.to]=1,que[tail++]=e.to; 76 } 77 } 78 } 79 Edge play[maxn]; 80 int fplay[maxn],lp; 81 int dis[maxn]; 82 void inplay(int x,int y) 83 { 84 play[lp].to=y; 85 play[lp].next=fplay[x]; 86 fplay[x]=lp++; 87 } 88 void dijkstra(int x) 89 { 90 priority_queue<qnode,vector<qnode>,greater<qnode> > q; 91 for (int i=fplay[x];i;i=play[i].next) 92 { 93 Edge &e=play[i]; 94 q.push((qnode){dis[e.to],e.to}); 95 vis[e.to]=0; 96 } 97 while (!q.empty()) 98 { 99 const int now=q.top().id,d=q.top().v;q.pop(); 100 if (vis[now]) continue; 101 vis[now]=1; 102 for (int i=froad[now];i;i=road[i].next) 103 { 104 Edge &e=road[i]; 105 if (dis[e.to]>d+e.v) 106 { 107 dis[e.to]=d+e.v; 108 q.push((qnode){dis[e.to],e.to}); 109 } 110 } 111 for (int i=ffly[now];i;i=fly[i].next) 112 { 113 Edge &e=fly[i]; 114 if (dis[e.to]>d+e.v) 115 { 116 dis[e.to]=d+e.v; 117 if (!vis[e.to]) 118 { 119 vis[e.to]=1; 120 inplay(find(e.to),e.to); 121 } 122 } 123 deg[find(e.to)]--; 124 if (!deg[ufs[e.to]]) que[tail++]=ufs[e.to]; 125 } 126 } 127 } 128 void solve() 129 { 130 bfs(); 131 for (int i=1;i<=n;i++) dis[i]=inf;dis[s]=0; 132 memset(fplay,0,sizeof(fplay));lp=2; 133 que[head=(tail=1)-1]=find(s); 134 inplay(ufs[s],s); 135 memset(vis,0,sizeof(vis)); 136 while (head!=tail) 137 { 138 const int now=que[head++]; 139 dijkstra(now); 140 } 141 for (int i=1;i<=n;i++) 142 printf(dis[i]==inf?"NO PATH\n":"%d\n",dis[i]); 143 } 144 }g; 145 int x,y,v; 146 int main() 147 { 148 scanf("%d%d%d%d",&n,&m1,&m2,&s); 149 ufsclear(n); 150 for (int i=1;i<=m1;i++) 151 { 152 scanf("%d%d%d",&x,&y,&v); 153 g.insert(x,y,v); 154 Union(x,y); 155 } 156 for (int i=1;i<=m2;i++) 157 { 158 scanf("%d%d%d",&x,&y,&v); 159 g.in(x,y,v); 160 } 161 g.solve(); 162 return 0; 163 }
View Code

BZOJ2200: [Usaco2011 Jan]道路和航線