FZU1009 Jogging Trails

来源:互联网 发布:网络诈骗代办信用卡 编辑:程序博客网 时间:2024/05/19 00:39

这道题对于Dijkstra的巧妙应用很神奇!

题意:

它让我们经过每条边至少一次,然后回到原点,求可以达到要求的最短的总路径


:(这样重复经过的边就可以当成是我们增加上去的)

我们可以这样理解:在原图的基础上增加一些边,使得这个图是欧拉回路,即每个点的度都是偶数

由于只有15个点我们可以用状态压缩,相应位置1表示这个点度数是偶数;

对于一个状态,加一条边则两个点奇偶性变了,相应位置取反,到达下一给状态

我们的目的就是求dis[111111111]时的边的总长度,初始状态就是各点原来的奇偶性组成

(如果两个点之间有多条边,则只保存最短的那条边,这样总长度才会最小)

#include <stdio.h>#include <string.h>#include <queue>using namespace std;const int maxn = 15+1;const int maxm = 1<<maxn;struct Node{    int pos, dist;    Node (int pos, int dist)    {        this->pos = pos;        this->dist = dist;    }    bool operator<(const struct Node &ans)const    {        return dist > ans.dist;    }};int degree[maxn], edge[maxn][maxn], dis[maxm];bool vis[maxm];int n, m, st, ed, sum;void Init(){    for(int i = 0; i < n; i++)    {        degree[i] = 0;        for(int j = 0; j < n; j++)            edge[i][j] = -1;    }    int a, b, c;    sum = 0;    for(int i = 0; i < m; i++)    {        scanf("%d%d%d", &a, &b, &c);        a--, b--;        degree[a]++, degree[b]++;        sum += c;        if(edge[a][b] == -1 || edge[a][b] > c)            edge[a][b] = edge[b][a] = c;    }    st = ed = 0;    for(int i = 0; i < n; i++)    {        ed |= (1<<i);//终点为全1,即所有点的度都为偶数        if(degree[i] % 2 == 0)            st |= (1<<i);//起点为原图的点的奇偶性    }}void Dijkstra(){    priority_queue<struct Node> myQue;    int up = 1 << n;    for(int i = 0; i < up; i++)        dis[i] = -1, vis[i] = false;    dis[st] = sum;    myQue.push(Node(st, dis[st]));    while(!myQue.empty())    {        Node ans = myQue.top();        myQue.pop();        int u = ans.pos;        if(vis[u])            continue;        vis[u] = true;        if(u == ed)            break;        for(int i = 0; i < n; i++)            for(int j = 0; j < i; j++)            {                if(edge[i][j] != -1)                {                    int v = u ^ (1<<i);                    v = v ^ (1<<j);//两个点取反达到下一个点                    if(dis[v] == -1 || dis[u] + edge[i][j] < dis[v])                    {                        dis[v] = dis[u] + edge[i][j];                        myQue.push(Node(v, dis[v]));                    }                }            }    }}int main(){    while(scanf("%d", &n) != EOF && n)    {        scanf("%d", &m);        Init();        Dijkstra();        printf("%d\n", dis[ed]);    }    return 0;}

原创粉丝点击