bzoj4289

最短路

很容易想到边和边之间连边,但是这样菊花图就完蛋了

我们想办法优化一下,能不能不要每条边都连。

考虑查分,把一个点的出边串起来,这样就行了,每条无向边拆成两条就能保证了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
namespace IO 
{
    const int Maxlen = N * 50;
    char buf[Maxlen], *C = buf;
    int Len;
    inline void read_in()
    {
        Len = fread(C, 1, Maxlen, stdin);
        buf[Len] = '\0';
    }
    inline void fread(int &x) 
    {
        x = 0;
        int f = 1;
        while (*C < '0' || '9' < *C) { if(*C == '-') f = -1; ++C; }
        while ('0' <= *C && *C <= '9') x = (x << 1) + (x << 3) + *C - '0', ++C;
        x *= f;
    }
    inline void fread(long long &x) 
    {
        x = 0;
        long long f = 1;
        while (*C < '0' || '9' < *C) { if(*C == '-') f = -1; ++C; }
        while ('0' <= *C && *C <= '9') x = (x << 1) + (x << 3) + *C - '0', ++C;
        x *= f;
    }
    inline void read(int &x)
    {
        x = 0;
        int f = 1; char c = getchar();
        while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
        while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + c - '0'; c = getchar(); }
        x *= f;
    }
    inline void read(long long &x)
    {
        x = 0;
        long long f = 1; char c = getchar();
        while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
        while(c >= '0' && c <= '9') { x = (x << 1ll) + (x << 3ll) + c - '0'; c = getchar(); }
        x *= f;
    } 
} using namespace IO;
int rd()
{
    int x = 0, f = 1;
    char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}
int n, cnt = 1, source, sink, m;
int head[N], hd[N * 8], st[N], vis[N * 8];
ll d[N * 8];
struct edge {
    int nxt, to, w;
} e[N * 8];
bool cmp(int i, int j) 
{
    return e[i].w < e[j].w;
}
void link(int *head, int u, int v, int w)
{
    e[++cnt].nxt = head[u];
    head[u] = cnt;
    e[cnt].to = v;
    e[cnt].w = w;
}
int main()
{
    read_in();
    fread(n);
    fread(m);
    for(int i = 1; i <= m; ++i)
    {
        int u, v, w;
        fread(u);
        fread(v);
        fread(w);
        link(head, u, v, w);
        link(head, v, u, w);
    }
    source = 0;
    sink = 6 * m + 1;
    for(int i = 1; i <= n; ++i)
    {
        int top = 0;
        for(int j = head[i]; j; j = e[j].nxt) st[++top] = j;
        sort(st + 1, st + top + 1, cmp);
        for(int j = 1; j <= top; ++j) 
        {
            int now = st[j], nxt = st[j + 1]; 
            if(i == 1) link(hd, source, now, e[now].w);
            if(e[now].to == n) link(hd, now, sink, e[now].w);
            link(hd, now, now ^ 1, e[now].w);
            if(j < top) 
            {
                link(hd, now, nxt, e[nxt].w - e[now].w);
                link(hd, nxt, now, 0);  
            }
        }
    }
    priority_queue<pair<ll, int>, vector<pair<ll, int> >, greater<pair<ll, int> > > q;
    memset(d, 0x3f3f, sizeof(d));
    d[source] = 0;
    q.push({0, source});
    while(!q.empty())
    {
        pair<ll, int> o = q.top();
        q.pop();
        int u = o.second;
        if(vis[u]) continue;
        vis[u] = 1;
        for(int i = hd[u]; i; i = e[i].nxt) if(d[e[i].to] > d[u] + e[i].w) 
        {
            d[e[i].to] = d[u] + e[i].w;
            q.push({d[e[i].to], e[i].to});
        }
    }
    printf("%lld\n", d[sink]);
    return 0;
}
View Code

 

posted @ 2017-12-08 07:50  19992147  阅读(199)  评论(0编辑  收藏  举报