JLOI 2011 飞行路线【分层图】

 

 

 

 

 

 思路

  诸如此类带路径使用次数有限制的题貌似都是要用到分层图来解决的问题

  通过把一张图分成k层相等的图

  这样当跑完dij后

  对于每一层图的终点来说

  意义就是:使用了 i 次免费路径到达终点时花费的最小值

  基本建图方法:

  对于道路的两个端点

  ①在每一层上把这两个点连起来,费用为w

  ②把每层之间的这两个点连起来,费用为0

  跑完最大流枚举每层的终点找最小值即可

 

CODE

 

  1 #include <bits/stdc++.h>
  2 #define dbg(x) cout << #x << "=" << x << endl
  3 #define eps 1e-8
  4 #define pi acos(-1.0)
  5 
  6 using namespace std;
  7 typedef long long LL;
  8 
  9 template<class T>inline void read(T &res)
 10 {
 11     char c;T flag=1;
 12     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
 13     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
 14 }
 15 
 16 namespace _buff {
 17     const size_t BUFF = 1 << 19;
 18     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
 19     char getc() {
 20         if (ib == ie) {
 21             ib = ibuf;
 22             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
 23         }
 24         return ib == ie ? -1 : *ib++;
 25     }
 26 }
 27 
 28 int qread() {
 29     using namespace _buff;
 30     int ret = 0;
 31     bool pos = true;
 32     char c = getc();
 33     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
 34         assert(~c);
 35     }
 36     if (c == '-') {
 37         pos = false;
 38         c = getc();
 39     }
 40     for (; c >= '0' && c <= '9'; c = getc()) {
 41         ret = (ret << 3) + (ret << 1) + (c ^ 48);
 42     }
 43     return pos ? ret : -ret;
 44 }
 45 
 46 const int maxn = 2e5 + 7;
 47 const int inf  = 0x3f3f3f3f;
 48 
 49 int head[maxn << 1], edge[maxn << 1], w[maxn << 1], nxt[maxn << 1];
 50 int cnt;
 51 
 52 inline void BuildGraph (int u, int v, int c) {
 53     cnt++;
 54     edge[cnt] = v;
 55     nxt[cnt]  = head[u];
 56     w[cnt] = c;
 57     head[u] = cnt;
 58 }
 59 
 60 struct node {
 61     int u,v;
 62     bool operator <(const node &t) const {
 63         return u > t.u;
 64     }
 65 };
 66 
 67 int n,m,s,t,k;
 68 int dis[maxn];
 69 bool vis[maxn << 1];
 70 
 71 priority_queue < node > q;
 72 
 73 void dijkstra(int s) {
 74     memset(dis, 0x3f, sizeof(dis));
 75     dis[s] = 0;
 76     node temp;
 77     temp.u = 0;
 78     temp.v = s;
 79     q.push(temp);
 80     while(!q.empty()) {
 81         int u = q.top().v;
 82         int d = q.top().u;
 83         q.pop();
 84         if(vis[u]) continue;
 85         vis[u] = true;
 86         for (int i = head[u]; i; i = nxt[i]) {
 87             int v = edge[i];
 88             int c = w[i];
 89             if(dis[v] > dis[u] + c) {
 90                 dis[v] = dis[u] + c;
 91                 node p;
 92                 p.u = dis[v], p.v = v;
 93                 q.push(p);
 94             }
 95         }
 96     }
 97 }
 98 
 99 int main()
100 {
101     read(n); read(m); read(k);
102     read(s); read(t);
103     ++s, ++t;
104     int u, v, w;
105     for ( int i = 1; i <= m; ++i ) {
106         read(u); read(v); read(w);
107         ++u, ++v;
108         BuildGraph(u, v, w);
109         BuildGraph(v, u, w);
110         for ( int j = 1; j <= k; ++j ) {
111             BuildGraph(u + (j - 1) * n, v + j * n, 0);
112             BuildGraph(v + (j - 1) * n, u + j * n, 0);
113             BuildGraph(u + j * n, v + j * n, w);
114             BuildGraph(v + j * n, u + j * n, w);
115         }
116     }
117     dijkstra(s);
118     int ans = INT_MAX;
119     for ( int i = 0; i <= k; ++i ) {
120         ans = min(ans, dis[t + i * n]);
121         //printf("dis[%d]:%d\n",t + i * n, dis[t + i * n]);
122     }
123     cout << ans << endl;
124     return 0;
125 }
View Code

 

posted @ 2020-05-07 10:08  Orangeko  阅读(202)  评论(0编辑  收藏  举报