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;}
- poj 2679题解
- POJ 1011 题解
- poj-1050 题解
- poj-1088题解
- poj-1159题解
- POJ 1009题解
- POJ 1458题解
- Poj 2352 Stars 题解
- POJ 2739题解---小菜
- POJ 1753题解
- POJ 1328题解
- POJ 2049题解
- poj 1149题解
- poj 2790迷宫题解
- POJ - Counterfeit Dollar 题解
- poj 2318 TOY题解
- POJ 1026 Cipher 题解
- POJ 1159 Palindrome 题解
- 嵌入式系统 Boot Loader 技术内幕
- 子网掩码和ip地址的关系&特殊用途的IP地址介绍
- Socket编程指南及示例程序
- ASP 获取文件的创建时间及修改时间
- 闪回数据归档
- poj 2679题解
- Oracle ORA-01578坏块处理
- Android 程序框架设计
- poj 1459 (最大流)
- Android聊天工具实现
- ZipUtil 历史上最好用的 压缩解压缩工具类 附代码
- ubuntu - eclipse 乱码
- Static block start new thread
- 正则表达式30分钟入门教程