游客 Signup | Login
中文 | En

2816 - 关键路径

描述:

    图的连接边上的数据表示其权值,带权值的图称作网。

<br />

<span style="font-size:10.5000pt;font-family:'宋体';">上图可描述为顶点集为</span><span style="font-size:10.5000pt;font-family:'Arial';">(<span>a,b,c,d,e)</span></span><span style="font-size:10.5000pt;font-family:'Arial';"></span> 

<span style="font-size:10.5000pt;font-family:'宋体';">边集及其权值为(始点,终点&nbsp;权值):</span><span style="font-size:10.5000pt;font-family:'Arial';">a&nbsp;b&nbsp;3</span><span style="font-size:10.5000pt;font-family:'Arial';"></span> 

<span style="font-size:10.5000pt;font-family:'Arial';">&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;c&nbsp;2&nbsp;</span><span style="font-size:10.5000pt;font-family:'Arial';"></span> 

<span style="font-size:10.5000pt;font-family:'Arial';">&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;d&nbsp;5</span><span style="font-size:10.5000pt;font-family:'Arial';"></span> 

<span style="font-size:10.5000pt;font-family:'Arial';">&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;d&nbsp;7</span><span style="font-size:10.5000pt;font-family:'Arial';"></span> 

<span style="font-size:10.5000pt;font-family:'Arial';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; c&nbsp;e&nbsp;4</span><span style="font-size:10.5000pt;font-family:'Arial';"></span> 

<span style="font-size:10.5000pt;font-family:'Arial';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d&nbsp;e&nbsp;6</span><span style="font-size:10.5000pt;font-family:'Arial';"> </span><span style="font-size:10.5000pt;font-family:'Arial';">&nbsp;&nbsp;</span><span style="font-size:10.5000pt;font-family:'宋体';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size:10.5000pt;font-family:'宋体';"></span> 

<span style="font-size:10.5000pt;font-family:'宋体';">&nbsp;&nbsp;</span><span style="font-size:10.5000pt;font-family:'宋体';">网的源点是入度为0的顶点,汇点是出度为0的顶点。网的关键路径是指</span><span style="color:#333333;font-weight:normal;font-style:normal;font-size:10.5000pt;font-family:'Arial';background:#FFFFFF;">从源点到汇点的所有路径中,具有最大路径长度的路径</span><span style="color:#333333;font-weight:normal;font-style:normal;font-size:10.5000pt;font-family:'宋体';background:#FFFFFF;">。上图中的关键路径为</span><span style="color:#333333;font-weight:normal;font-style:normal;font-size:10.5000pt;font-family:'宋体';background:#FFFFFF;">a-&gt;c-&gt;d-&gt;e<span>,其权值之和为关键路径的长度为</span><span>15</span><span>。</span></span><span style="color:#333333;font-weight:normal;font-style:normal;font-size:10.5000pt;font-family:'宋体';background:#FFFFFF;"></span> 

<span style="color:#333333;font-weight:normal;font-style:normal;font-size:10.5000pt;font-family:'宋体';background:#FFFFFF;">&nbsp;&nbsp;本题的要求是根据给出的网的邻接矩阵求该网的关键路径及其长度。</span><span style="color:#333333;font-weight:normal;font-style:normal;font-size:10.5000pt;font-family:'宋体';background:#FFFFFF;"></span> 

<br />

Input

第一行输入一个正整数n1<=n<=5),其代表测试数据数目,即图的数目

第二行输入x(1<=x<=15)代表顶点个数,y(1<=y<=19)代表边的条数

第三行给出图中的顶点集,共x个小写字母表示顶点

接下来每行给出一条边的始点和终点及其权值,用空格相隔,每行代表一条边。

Output

第一个输出是图的关键路径(用给出的字母表示顶点, 用括号将边括起来,顶点逗号相隔)

第二个输出是关键路径的长度

每个矩阵对应上面两个输出,两个输出在同一行用空格间隔,每个矩阵的输出占一行。


Examples

Input

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

Output

(a,c) (c,d) (d,e) 15
(a,c) (c,d) 6

Hint

作者:梁青青

Solution C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INF 1000000000
#define maxn 30

int G[maxn][maxn];
int dp[maxn];
char choice[maxn];
int N;

int DP(int i) {
if(dp[i] > 0) return dp[i];
for(int j = 0;j < N; j++) {
    if(G[i][j] != INF) {
        int s = DP(j) + G[i][j];
        if(s > dp[i]) {
            dp[i] = s;
            choice[i]=j;
        }
    }
}
return dp[i];
}

void print(int i) {
    int flag=0;
    while(choice[i] != -1) {
        printf("(%c,%c) ",i+'a',choice[i]+'a');
        i = choice[i];
    }
}

int main()
{
    int n;
    while(scanf("%d",&n) != EOF) {
        while(n--) {
            int x, y;
            scanf("%d%d",&x,&y);
            N = x;
            for(int i = 0;i < maxn; i++) {
                for(int j = 0;j < maxn; j++)G[i][j]=INF;
            }
            char temp[maxn];
            scanf("%s",temp);
            for(int i = 0;i < y; i++) {
                char temp1, temp2;
                int temp3;
                getchar();
                scanf("%c",&temp1);
                getchar();
                scanf("%c",&temp2);
                getchar();
                scanf("%d",&temp3);
                G[temp1-'a'][temp2-'a']=temp3;
            }
            memset(dp,0,sizeof(dp));
            memset(choice,-1,sizeof(choice));
            int len = DP(0);
            print(0);
            printf("%d\n",len);
        }
    }

    return 0;
}

Solution C++

#include <stdio.h>
#include <stdlib.h>
#include <stack>
using namespace std;
#define INFINITY INT_MAX  
#define MAX_VERTEX_NUM 15

/****   图的邻接表存储表示   ****/
typedef struct ArcNode
{
	int adjvex; //该弧所指向的顶点的位置
	struct ArcNode *nextarc; //指向下一条弧的指针
	int w;//权值
}ArcNode;
typedef struct VNode
{
	char data; //顶点信息
	ArcNode *firstarc; //指向第一条依附该点的弧的指针
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct
{
	AdjList vertices;
	int vexnum, arcnum; //图的当前顶点数和弧数
}ALGraph;
int LocateVex_biao(ALGraph G, char v)
{
	for (int i = 0; i < G.vexnum; i++)
	{
		if (G.vertices[i].data == v) return i;
	}
}
int CreateDN_biao(ALGraph &G)
{
	//采用数组(邻接表)表示法,构造有向网G
	char v1, v2;//一条边所依附的两个顶点
	int w;//边的权值
	int i, j;
	scanf("%d%d", &G.vexnum, &G.arcnum);
	getchar();
	for (i = 0; i < G.vexnum; i++)
	{
		scanf("%c", &G.vertices[i].data);//构造顶点向量
		G.vertices[i].firstarc = NULL;
	}
	for (int k = 0; k < G.arcnum; k++)
	{
		getchar();
		scanf("%c", &v1);
		getchar();
		scanf("%c", &v2);
		getchar();
		scanf("%d", &w);
		i = LocateVex_biao(G, v1);
		j = LocateVex_biao(G, v2);
		if (G.vertices[i].firstarc == NULL)
		{
			G.vertices[i].firstarc = (ArcNode*)malloc(sizeof(ArcNode));
			G.vertices[i].firstarc->adjvex = j;
			G.vertices[i].firstarc->nextarc = NULL;
			G.vertices[i].firstarc->w = w;
		}
		else
		{
			ArcNode* p = G.vertices[i].firstarc;
			ArcNode* q;
			while (p->nextarc != NULL)
				p = p->nextarc;
			q = (ArcNode*)malloc(sizeof(ArcNode));
			q->adjvex = j;
			q->nextarc = NULL;
			q->w = w;
			p->nextarc = q;
		}
	}
	return 1;
}

/********  关键路径  *******/
int vl[MAX_VERTEX_NUM];
int ve[MAX_VERTEX_NUM];
void FindInDegree(ALGraph G, int *indegree)
{
	for (int j = 0; j < G.vexnum; j++)
	{
		indegree[j] = 0;//初始化
	}
	for (int i = 0; i < G.vexnum; i++)
	{
		ArcNode* p = G.vertices[i].firstarc;
		while (p != NULL)
		{
			indegree[p->adjvex]++;
			p = p->nextarc;
		}
	}
}
int TopologicalOrder(ALGraph G, stack<int> &T)
{
	int indegree[MAX_VERTEX_NUM];
	int i, j, k;
	stack<int> S;
	ArcNode* p;

	FindInDegree(G, indegree); //对个顶点求入度

	for (i = 0; i < G.vexnum; i++)
	{
		if (indegree[i] == 0)  S.push(i);//将入度为0的顶点入S栈
	}
	int count = 0;
	for (i = 0; i < G.vexnum; i++)  ve[i] = 0;

	while (!S.empty())
	{
		j = S.top(); S.pop();
		T.push(j); ++count;//j号顶点出S栈,入T栈,并计数
		for (p = G.vertices[j].firstarc; p; p = p->nextarc)
		{
			k = p->adjvex; //对j号顶点的每个邻接点的入度减1
			if (--indegree[k] == 0) S.push(k);//若入度为0,则入S栈
			if ((ve[j] + p->w) > ve[k]) ve[k] = ve[j] + p->w;
		}//for
	}//while
	if (count < G.vexnum)  return 0;
	else return 1;
}
int CriticalPath(ALGraph G)
{
	stack<int> T;
	int i, j, k, dut;
	ArcNode *p,*q;

	int ee, el;
	char tag;

	if (!TopologicalOrder(G, T)) return 0;
	for (i = 0; i < G.vexnum; i++) vl[i] = ve[G.vexnum-1];
	while (!T.empty())
	{
		for (j = T.top(), T.pop(), p = G.vertices[j].firstarc; p; p = p->nextarc)
		{
			k = p->adjvex;
			dut = p->w;
			if (vl[k] - dut < vl[j]) vl[j] = vl[k] - dut;
		}//for
	}//while
	k = 0;
	for (q = G.vertices[0].firstarc; q; )
	{
		int temp = k;
		for (p = q; p; p = p->nextarc)
		{
			k = p->adjvex;
			dut = p->w;
			ee = ve[temp];
			el = vl[k] - dut;
			tag = (ee == el) ? '*' : ' ';
			if (tag == '*')
			{
				printf("(%c,%c) ", G.vertices[temp].data, G.vertices[k].data);
				q = G.vertices[k].firstarc;
				break;
			}			
		}//for
	}//for
	printf("%d\n", ve[G.vexnum - 1]);
}//CriticalPath
int main()
{
	int n;
	ALGraph G1;

	scanf("%d", &n);
	while (n--)
	{
		CreateDN_biao(G1);
		CriticalPath(G1);
	}
	return 0;
}

Hint

作者:梁青青

Time Limit 1 second
Memory Limit 128 MB
Discuss Stats
上一题 下一题