[AHOI2008]上学路线

嘟嘟嘟

 

这道题其实挺显然的。

首先dijkstra跑出最短路图,然后在最短路图上求最小割。

正确性显然。

需要注意的是,在新图中添加最短路图的边的时候,一定是跑完dijkstra再加边,如果边跑dijkstra边加边,得到的是最短路树,而不是。我因为这个WA了好几发。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 using namespace std;
 12 #define enter puts("") 
 13 #define space putchar(' ')
 14 #define Mem(a, x) memset(a, x, sizeof(a))
 15 #define rg register
 16 typedef long long ll;
 17 typedef double db;
 18 const int INF = 0x3f3f3f3f;
 19 const db eps = 1e-8;
 20 const int maxn = 505;
 21 const int maxe = 1.3e5 + 5;
 22 inline ll read()
 23 {
 24   ll ans = 0;
 25   char ch = getchar(), last = ' ';
 26   while(!isdigit(ch)) {last = ch; ch = getchar();}
 27   while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
 28   if(last == '-') ans = -ans;
 29   return ans;
 30 }
 31 inline void write(ll x)
 32 {
 33   if(x < 0) x = -x, putchar('-');
 34   if(x >= 10) write(x / 10);
 35   putchar(x % 10 + '0');
 36 }
 37 
 38 int n, m;
 39 struct Edge1
 40 {
 41   int nxt, to, t, c;
 42 }e1[maxe << 1];
 43 int head1[maxn], ecnt1 = -1;
 44 void addEdge1(int x, int y, int t, int c)
 45 {
 46   e1[++ecnt1] = (Edge1){head1[x], y, t, c};
 47   head1[x] = ecnt1;
 48 }
 49 
 50 struct Edge2
 51 {
 52   int nxt, from, to, cap, flow;
 53 }e2[maxe << 2];
 54 int head2[maxn], ecnt2 = -1;
 55 void addEdge2(int from, int to, int w)
 56 {
 57   e2[++ecnt2] = (Edge2){head2[from], from, to, w, 0};
 58   head2[from] = ecnt2;
 59   e2[++ecnt2] = (Edge2){head2[to], to, from, 0, 0};
 60   head2[to] = ecnt2;
 61 }
 62 
 63 #define pr pair<int, int>
 64 #define mp make_pair
 65 bool in[maxn];
 66 int dis[maxn];
 67 void dijkstra(int s)
 68 {
 69   Mem(dis, 0x3f); dis[s] = 0;
 70   priority_queue<pr, vector<pr>, greater<pr> > q;
 71   q.push(mp(dis[s], s));
 72   while(!q.empty())
 73     {
 74       int now = q.top().second; q.pop();
 75       if(in[now]) continue;
 76       in[now] = 1;
 77       for(int i = head1[now]; i != -1; i = e1[i].nxt)
 78     {
 79       if(dis[e1[i].to] > dis[now] + e1[i].t)
 80         {
 81           dis[e1[i].to] = dis[now] + e1[i].t;
 82           q.push(mp(dis[e1[i].to], e1[i].to));
 83         }
 84     }
 85     }
 86 }
 87 
 88 int dis2[maxn];
 89 bool bfs()
 90 {
 91   Mem(dis2, 0); dis2[1] = 1;
 92   queue<int> q; q.push(1);
 93   while(!q.empty())
 94     {
 95       int now = q.front(); q.pop();
 96       for(int i = head2[now]; i != -1; i = e2[i].nxt)
 97     {
 98       if(!dis2[e2[i].to] && e2[i].cap > e2[i].flow)
 99         {
100           dis2[e2[i].to] = dis2[now] + 1;
101           q.push(e2[i].to);
102         }
103     }
104     }
105   return dis2[n];
106 }
107 int cur[maxn];
108 int dfs(int now, int res)
109 {
110   if(now == n || res == 0) return res;
111   int flow = 0, f;
112   for(int &i = cur[now]; i != -1; i = e2[i].nxt)
113     {
114       if(dis2[e2[i].to] == dis2[now] + 1 && (f = dfs(e2[i].to, min(res, e2[i].cap - e2[i].flow))) > 0)
115     {
116       e2[i].flow += f; e2[i ^ 1].flow -= f;
117       flow += f; res -= f;
118       if(res == 0) break;
119     }
120     }
121   return flow;
122 }
123 
124 int minCut()
125 {
126   int flow = 0;
127   while(bfs())
128     {
129       memcpy(cur, head2, sizeof(head2));
130       flow += dfs(1, INF);
131     }
132   return flow;
133 }
134 
135 int main()
136 {
137   Mem(head1, -1); Mem(head2, -1);
138   n = read(); m = read();
139   for(int i = 1; i <= m; ++i)
140     {
141       int x = read(), y = read(), t = read(), c = read();
142       addEdge1(x, y, t, c); addEdge1(y, x, t, c);
143     }
144   dijkstra(1);
145   for(int i = 1; i <= n; ++i)
146     for(int j = head1[i]; j != -1; j = e1[j].nxt)
147       if(dis[e1[j].to] == dis[i] + e1[j].t) addEdge2(i, e1[j].to, e1[j].c);
148   write(dis[n]), enter, write(minCut()), enter;
149   return 0;
150 }
View Code

 

posted @ 2018-10-24 10:06  mrclr  阅读(252)  评论(0编辑  收藏  举报