poj 2679题解

来源:互联网 发布:js mouseover 提示 编辑:程序博客网 时间:2024/05/22 10:49

题目来源:http://poj.org/problem?id=2679

题目描述:

给你一个很复杂的图(输入很蛋疼。。。),每条路径有两个权值(fee,length),让你求某两个点之间fee值最短的路径,如果存在两条最短路则选择length值最小的路径。但是还存在某些限制

1、如果这两点之间没有路径则输出VOID

2、如果这两点之间的路径上有负环则输出UNBOUND

3、从某个点去向其他点(包括自己)的路径只能选择fee值最小的。

大体就是这个意思,由于我不想用邻接表写。。所以只能乱搞了一下(因为n^3的算法会超时)。

1、首先判断这两点之间是否存在路径,如果不存在直接输出,并退出;

2、如果存在路径,在判断起始点是否有自连的负环,如果有直接输出UNBOUND;

3、上述两者都满足的条件下,用spfa算法,当有某个点进队n次以上的时候,说明这个点在某个负环上,用dfs判断此点和终点是否有路径,如果有则直接输出UNBOUND,退出,否则,标记该点,不让他在进队,continue。


代码如下:

#include <iostream>#include <cstring>#include <cstdio>#include <fstream>#include <queue>#define INF 99999999using namespace std;struct edge{    int fee;    int length;};edge edges[1101][1101];bool visited[1101];int dis[1101];int count[1101];bool fff[1101];int len[1101];int n,m,first,last;bool vis[1101];bool dfs(int a,int b){    if(b == a)        return true;    vis[a] = true;    for(int i = 1 ; i <= n ; i++)    {        if(a != i && !vis[i] && edges[a][i].length < INF)        {            vis[i] = true;            if(dfs(i,b))                return true;        }    }    return false;}int spfa(){    for (int i = 1 ; i <= n; i++)//初始化    {        count[i] = 0;        dis[i] = INF;        visited[i] = false;        fff[i] = false;        len[i] = 0;    }    queue<int> Q;    dis[first] = 0;    count[first] = 1;    visited[first] = true;    Q.push(first);    while (!Q.empty())    {        int temp = Q.front();        //cout<<temp<<endl;        Q.pop();        visited[temp] = false;        if(count[temp] > n)        {            //cout<<temp<<endl;            fff[temp] = true;            memset(vis,false,sizeof(vis));            if(dfs(temp,last))            {                //cout<<temp<<' '<<last<<endl;                return -1;//Unbound;            }            else                continue;        }        for (int i = 1 ; i <= n; i++)        {            if (edges[temp][i].length < INF && dis[temp] + edges[temp][i].fee <= dis[i])            {                if(dis[temp] + edges[temp][i].fee < dis[i])                {                    len[i] = len[temp] + edges[temp][i].length;                    dis[i] = dis[temp] + edges[temp][i].fee;                    if (!visited[i] && !fff[temp])                    {                        Q.push(i);                        count[i]++;                        visited[i] = true;                    }                }                else if(len[temp] + edges[temp][i].length < len[i])                {                    len[i] = len[temp] + edges[temp][i].length;                    if (!visited[i] && !fff[temp])                    {                        Q.push(i);                        count[i]++;                        visited[i] = true;                    }                }            }        }    }    if(dis[last] == INF)        return 0;//VOID    else        return 1;}int main(){    int u,v,fuv,fvu,le;    char ch;    while(scanf("%d%d%d%d",&n,&m,&first,&last)!=EOF)    {        first++;        last++;        for(int i = 1 ; i <= n ; i++)            for(int j = 1 ; j <= n ; j++)            {                edges[i][j].fee = 0;                edges[i][j].length = INF;            }        for(int i = 1 ; i <= m; i++)        {            scanf(" %c%d%c%d%c%d%c%d%c%d%c",&ch,&u,&ch,&v,&ch,&fuv,&ch,&le,&ch,&fvu,&ch);            if(edges[u + 1][v + 1].length == INF)            {                if(u != v)                {                    edges[u + 1][v + 1].fee = fuv;                    edges[v + 1][u + 1].fee = fvu;                    edges[u + 1][v + 1].length = edges[v + 1][u + 1].length = le;                }                else                {                    edges[u + 1][v + 1].fee = fuv < fvu ? fuv : fvu;                    edges[u + 1][v + 1].length = edges[v + 1][u + 1].length = le;                }            }            else            {                if(edges[u + 1][v + 1].fee >= fuv)                {                    if(edges[u + 1][v + 1].fee > fuv)                    {                        edges[u + 1][v + 1].fee = fuv;                        edges[u + 1][v + 1].length = le;                    }                    else                    {                        edges[u + 1][v + 1].length = edges[u + 1][v + 1].length < le ? edges[u + 1][v + 1].length : le;                    }                }                if(edges[v + 1][u + 1].fee >= fvu)                {                    if(edges[v + 1][u + 1].fee > fvu)                    {                        edges[v + 1][u + 1].fee = fvu;                        edges[v + 1][u + 1].length = le;                    }                    else                    {                        edges[v + 1][u + 1].length = edges[v + 1][u + 1].length < le ? edges[v + 1][u + 1].length : le;                    }                }            }        }        for(int i = 1 ; i <= n; i++)        {            int min = INF;            for(int j = 1 ; j <= n ; j++)            {                if(edges[i][j].length < INF && min > edges[i][j].fee)                    min = edges[i][j].fee;            }            if(min != INF)            {                for(int j = 1 ; j <= n ; j++)                {                    if(min < edges[i][j].fee)                    {                        edges[i][j].length = INF;                        edges[i][j].fee = 0;                    }                }            }        }        memset(vis,false,sizeof(vis));        ofstream out("2679.txt",ios::out);        if(!dfs(first,last))        {            cout<<"VOID\n";            continue;        }        if(edges[first][first].length < INF && edges[first][first].fee < 0)        {            cout<<"UNBOUND\n";            continue;        }        memset(vis,false,sizeof(vis));        int ans = spfa();        if(ans == -1)            cout<<"UNBOUND\n";        else if(ans == 0)            cout<<"VOID\n";        else            cout<<dis[last]<<' '<<len[last]<<endl;    }    return 0;}

原创粉丝点击