时间限制 : 1.000 sec 内存限制 : 128 MB
题目描述
描述:
图的连接边上的数据表示其权值,带权值的图称作网。
上图可描述为顶点集为(a,b,c,d,e)
边集及其权值为(始点,终点 权值):
a b 3
a c 2
b d 5
c d 7
c e 4
d e 6
网的源点是入度为0的顶点,汇点是出度为0的顶点。网的关键路径是指从源点到汇点的所有路径中,具有最大路径长度的路径。上图中的关键路径为a->c->d->e,其权值之和为关键路径的长度为15。
本题的要求是根据给出的网的邻接矩阵求该网的关键路径及其长度。
输入
第一行输入一个正整数n(1<=n<=5),其代表测试数据数目,即图的数目
第二行输入x(1<=x<=15)代表顶点个数,y(1<=y<=19)代表边的条数
第三行给出图中的顶点集,共x个小写字母表示顶点
接下来每行给出一条边的始点和终点及其权值,用空格相隔,每行代表一条边。
输出
第一个输出是图的关键路径(用给出的字母表示顶点, 用括号将边括起来,顶点逗号相隔)
第二个输出是关键路径的长度
每个矩阵对应上面两个输出,两个输出在同一行用空格间隔,每个矩阵的输出占一行。
样例输入
2
5 6
abcde
a b 3
a c 2
b d 5
c d 7
c e 4
d e 6
4 5
abcd
a b 2
a c 3
a d 4
b d 1
c d 3
样例输出
(a,c) (c,d) (d,e) 15
(a,c) (c,d) 6
注意:每次求出ve[u] == vl[v] - weight表示这条边是关键路径中的一条边。如果有多条关键路径,输出的时候只需要输出一条关键路径就行了。所以需要新建一个vector来存储关键路径。
样例:
1
4 4
abcd
a b 3
a c 3
b d 4
c d 4
(a,b) (b,d) 7
(a,c) (c,d) 7//只需要两条路径中输出一条即可;
#include <iostream>
#include <cstdio>
#include <map>
#include <vector>
#include <string>
#include <memory.h>
#include <set>
#include <stack>
#include <queue>
#include <unordered_map>
#include <iomanip>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 1010;
struct node {
int v, dis;
};
vector<node > g[maxn];
vector<int > pre[maxn];
stack<int > toporder;
unordered_map<char,int > map1;
unordered_map<int,char > map2;
int n, x, y, w, ve[maxn], vl[maxn], indegree[maxn];
void maketoporder() {
fill(ve, ve + maxn, 0);
queue<int > q;
for (int i = 0; i < x; i++) {
if (indegree[i] == 0)
q.push(i);
}
while (!q.empty()) {
int u = q.front();
q.pop();
toporder.push(u);
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i].v;
indegree[v]--;
if (indegree[v] == 0)
q.push(v);
if (ve[u] + g[u][i].dis > ve[v])
ve[v] = ve[u] + g[u][i].dis;
}
}
}
int findendv() {//对每个点的ve遍历,最大值就是汇点的路径长度
int maxv = -1;
for (int i = 0; i < x; i++) {
if (ve[i] > maxv)
maxv = ve[i];
}
return maxv;
}
void criticalpath() {
while (!toporder.empty()) {
int u = toporder.top();
toporder.pop();
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i].v;
if (vl[v] - g[u][i].dis < vl[u]) {
vl[u] = vl[v] - g[u][i].dis;
}
}
}
//(a,c) (c,d) (d,e) 15
for (int u = 0; u < x; u++) {
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i].v, weight = g[u][i].dis;
if (ve[u] == vl[v] - weight) {
pre[u].push_back(v);
}
}
}
int prei;
for (int i = 0; i < x; i++) {//找起点
if (ve[i] == 0) {
prei = i;
break;
}
}
while (pre[prei].size() != 0) {
printf("(%c,%c) ", map2[prei], map2[pre[prei][0]]);
prei = pre[prei][0];
}
}
int main() {
char c, u, v;
cin >> n;
while (n--) {
for (int i = 0; i < maxn; i++) {
g[i].clear();
pre[i].clear();
}
fill(indegree, indegree + maxn, 0);
map1.clear();
map2.clear();
cin >> x >> y;
for (int i = 0; i < x; i++) {//给结点编号
cin >> c;
map1[c] = i;
map2[i] = c;
}
for (int i = 0; i < y; i++) {//邻接表存储图
cin >> u >> v >> w;
indegree[map1[v]]++;
node temp;
temp.v = map1[v];
temp.dis = w;
g[map1[u]].push_back(temp);
}
maketoporder();
int end1 = findendv();//找到关键路径长度
fill(vl, vl + maxn, end1);//初始化vl
criticalpath();
printf("%d\n", end1);
}
return 0;
}