数据结构 实验7

/*8647 实现图的存储结构
Description
实现有向图的邻接矩阵存储结构。
输入格式
第一行:输入图的顶点个数n(各个顶点的默认编号为1~n), 边的条数m。
第二 ~ m+1行:每行输入两个顶点编号i、j,表示连接顶点i到顶点j的一条边。
输出格式
分n行输出n*n的邻接矩阵,表示所输入的图存储,顶点i和顶点j之间如果有边相连,则输出1,没边相连则输出0。
输入样例
4 4
1 2
1 3
3 4
4 1
输出样例
0 1 1 0
0 0 0 0
0 0 0 1
1 0 0 0*/

#include <iostream>
using namespace std;

const int N = 110;

int n, m;
int g[N][N];

int main()
{
    // 输入n和m
    cin >> n >> m;

    // 读入m条边
    while (m -- )
    {
        int a, b;
        cin >> a >> b;
        // 存储图中的边
        g[a][b] = 1;
    }

    // 输出邻接矩阵
    for (int i = 1; i <= n; i ++ )
    {
        for (int j = 1; j <= n; j ++ )
            // 输出g[i][j]
            cout << g[i][j] << ' ';
        // 换行
        cout << endl;
    }

    return 0;
}
/*8648 图的深度遍历
Description 实现图的邻接表存储结构及一些基本操作函数。在此基础上实现图的深度遍历算法并加以测试。本题只给出部分代码,请补全内容。
输入格式
第一行:输入0到3之间整数(有向图:0,有向网:1,无向图:2,无向网:3);
第二行:输入顶点数和边数;
第三行:输入各个顶点的值(字符型,长度〈3);(遍历从输入的第一个顶点开始)
第四行:输入每条弧(边)弧尾和弧头(以空格作为间隔),如果是网还要输入权值;
输出格式
输出对图深度遍历的结果。
输入样例
0
3 3     
a b c
a b
b c
c b
输出样例
a b c
*/
#include"string.h" 
#include"malloc.h" /* malloc()等 */ 
#include"stdio.h" /* EOF(=^Z或F6),NULL */ 
#include"stdlib.h" /* exit() */ 
typedef int InfoType; /* 顶点权值类型 */ 
#define MAX_NAME 3 /* 顶点字符串的最大长度+1 */ 
typedef char VertexType[MAX_NAME]; /* 字符串类型 */ 
/*图的邻接表存储表示 */ 
#define MAX_VERTEX_NUM 20 
typedef enum{DG,DN,AG,AN}GraphKind; /* {有向图,有向网,无向图,无向网} */ 
typedef struct ArcNode 
{ 
	int adjvex; /* 该弧所指向的顶点的位置 */ 
	struct ArcNode *nextarc; /* 指向下一条弧的指针 */ 
	InfoType *info; /* 网的权值指针) */ 
}ArcNode; /* 表结点 */ 

typedef struct 
{ 
	VertexType data; /* 顶点信息 */ 
	ArcNode *firstarc; /* 第一个表结点的地址,指向第一条依附该顶点的弧的指针 */ 
}VNode,AdjList[MAX_VERTEX_NUM]; /* 头结点 */ 

typedef struct 
{ 
	AdjList vertices; 
	int vexnum,arcnum; /* 图的当前顶点数和弧数 */ 
	int kind; /* 图的种类标志 */ 
}ALGraph; 

int LocateVex(ALGraph G,VertexType u) 
{ /* 初始条件: 图G存在,u和G中顶点有相同特征 */ 
/* 操作结果: 若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */ 
	int i; 
	for(i=0;i<G.vexnum;++i) 
		if(strcmp(u,G.vertices[i].data)==0) 
			return i; 
	return -1; 
} 

void CreateGraph(ALGraph *G) 
{ /* 采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4种图) */ 
	int i,j,k; 
	int w; /* 权值 */ 
	VertexType va,vb; 
	ArcNode *p; 
	//printf("Enter the type of map:(0~3): "); 
	scanf("%d",&(*G).kind); 
	//printf("Enter Vertex number,Arc number: "); 
	scanf("%d%d",&(*G).vexnum,&(*G).arcnum); 
	//printf("Enter %d Vertex :\n",(*G).vexnum); 
	for(i=0;i<(*G).vexnum;++i) /* 构造顶点向量 */ 
	{ 
		scanf("%s",(*G).vertices[i].data); 
		(*G).vertices[i].firstarc=NULL; 
	} 
	//if((*G).kind==1||(*G).kind==3) /* 网 */ 
	//	printf("Enter order every arc weight,head and tail (Takes the gap by the blank space ):\n"); 
	//else /* 图 */ 
	//	printf("Enter order every arc head and tail (Takes the gap by the blank space ):\n"); 
	for(k=0;k<(*G).arcnum;++k) /* 构造表结点链表 */ 
	{ 
		scanf("%s %s", va, vb);
        i = LocateVex(*G, va);
        j = LocateVex(*G, vb);
        p = (ArcNode*)malloc(sizeof(ArcNode));
        p->adjvex = j;
        p->nextarc = (*G).vertices[i].firstarc;
        (*G).vertices[i].firstarc = p;
        if ((*G).kind == 1 || (*G).kind == 3) {
            p->info = (int*)malloc(sizeof(int));
            scanf("%d", p->info);
        }
	} 
} 

void DFS(ALGraph G, int v, int visited[]) {
    visited[v] = 1;
    printf("%s ", G.vertices[v].data);
    ArcNode* p = G.vertices[v].firstarc;
    while (p) {
        if (!visited[p->adjvex]) {
            DFS(G, p->adjvex, visited);
        }
        p = p->nextarc;
    }
}

void DFSTraverse(ALGraph G) {
    int visited[MAX_VERTEX_NUM];
    for (int i = 0; i < G.vexnum; i++) {
        visited[i] = 0;
    }
    for (int i = 0; i < G.vexnum; i++) {
        if (!visited[i]) {
            DFS(G, i, visited);
        }
    }
}

int main() {
    ALGraph G;
    CreateGraph(&G);
    DFSTraverse(G);
    return 0;
} 

/*18448 最小生成树
Description
给定结点数为n,边数为m的带权无向连通图G,所有结点编号为1,2,3....n。
求图G的最小生成树的边权和。
输入格式
第一行两个正整数n和m。n,m<=2000
之后的m行,每行三个正整数a,b,w,描述一条连接结点a和b,边权为w的边。1=<a,b<=n,w<=10^18。
注意可能存在重边和自环。
输出格式
一个整数表示图G的最小生成树的边权和(注意用长整型)。
输入样例
7 12
1 2 9
1 5 2
1 6 3
2 3 5
2 6 7
3 4 6
3 7 3
4 5 6
4 7 2
5 6 3
5 7 6
6 7 1
输出样例
16*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 2010, M = 4000010;

int n, m;
int h[N], e[M], ne[M], w[M], idx; // h[i]表示第i个点的所有边的编号,e[i]表示第i条边的另一个端点,ne[i]表示第i条边的下一条边的编号,w[i]表示第i条边的权重,idx表示当前边的编号
int dist[N]; // dist[i]表示第i个点到最小生成树的距离
bool st[N]; // st[i]表示第i个点是否已经在最小生成树中

void add(int a, int b, int c) // 添加一条边a->b,边权为c
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ; // 将边的信息存储在数组中,同时更新h数组和idx
}

long long prim() // 返回最小生成树的边权和,如果图不连通则返回0x3f3f3f3f3f3f3f3f
{
    memset(dist, 0x3f, sizeof dist); // 初始化dist数组为无穷大
    long long res = 0; // 存储最小生成树的边权和

    for (int i = 0; i < n; i ++ ) // 执行n次
    {
        int t = -1; // t表示距离最小生成树最近的点
        for (int j = 1; j <= n; j ++ ) // 找到距离最小生成树最近的点
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;

        if (i && dist[t] == 0x3f3f3f3f) return 0x3f3f3f3f3f3f3f3f; // 如果t没有被更新过,说明图不连通,返回无穷大
        if (i) res += dist[t]; // 将t到最小生成树的距离加入res
        st[t] = true; // 将t加入最小生成树

        for (int j = h[t]; ~j; j = ne[j]) // 更新t的所有出边
        {
            int k = e[j]; // k表示t的一个出边的另一个端点
            if (!st[k]) dist[k] = min(dist[k], w[j]); // 如果k不在最小生成树中,更新k到最小生成树的距离
        }
    }

    return res; // 返回最小生成树的边权和
}

int main()
{
    memset(h, -1, sizeof h); // 初始化h数组为-1

    cin >> n >> m; // 输入点数和边数
    while (m -- ) // 输入每一条边
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c); // 添加双向边
    }

    cout << prim() << endl; // 输出最小生成树的边权和

    return 0;
}

/*18732 最短路问题
Description
现在有n个车站和m条直达公交线路,每条线路都有一个固定票价。
作为一个窮人,你打算从车站1坐车到车站n,请计算下车站1到车站n的最少花费。
如果车站1无法到达车站n,请输出-1。
注意,在车站x和y之间可能存在不止一条线路。
输入格式
第一行两个整数n和m,表示车站数量和线路数量。(1<=n<=100),(1<=m<=1000)
第二行至第m+1行,每行3个整数a,b,x,代表车站a和车站b之间有一条票价为x的公交线路,公交线路是双向的。
输出格式
输出车站1到n的最小花费。
输入样例
4 4
1 2 4
2 3 7
2 4 1
3 4 6
输出样例
5*/
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 110, M = 2010;

int n, m;
int h[N], e[M], w[M], ne[M], idx;
int dist[N]; // dist[i]表示1号点到i号点的最短距离
bool st[N]; // st[i]表示i号点是否已经确定最短路

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ; // 添加一条a到b的边,边权为c
}

int dijkstra()
{
    memset(dist, 0x3f, sizeof dist); // 初始化,1号点到其它各个点的距离均为正无穷
    dist[1] = 0; // 1号点到1号点的距离为0

    for (int i = 0; i < n; i ++ ) // 进行n次操作
    {
        int t = -1; // 在还未确定最短路的点中,寻找距离最小的点
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;

        if (t == -1) break; // 如果没有找到,说明剩下的点和起点不连通
        st[t] = true; // 确定一个点的最短路

        for (int j = h[t]; ~j; j = ne[j]) // 用t更新其他点的距离
        {
            int ver = e[j], distance = w[j];
            if (dist[ver] > dist[t] + distance)
                dist[ver] = dist[t] + distance; // 通过t进行松弛操作
        }
    }

    if (dist[n] == 0x3f3f3f3f) return -1; // 无法从1号点走到n号点
    return dist[n]; // 返回1号点到n号点的最短距离
}

int main()
{
    memset(h, -1, sizeof h); // 初始化邻接表

    cin >> n >> m; // n表示点数,m表示边数
    while (m -- )
    {
        int a, b, c;
        cin >> a >> b >> c; // 读入一条边
        add(a, b, c), add(b, a, c); // 存储无向图
    }

    cout << dijkstra() << endl; // 输出1号点到n号点的最短距离

    return 0;
}

/*
标程

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int n,m,v[105],d[105];
struct node
{
    int adj,val;
};
vector<node>e[105];
int getmin()
{
    int i,minv=999999999,mini=0;
    for(i=1; i<=n; i++)
    {
        if(v[i]==0&&minv>d[i])
        {
            mini=i;
            minv=d[i];
        }
    }
    return mini;
}
void djstra(int s)
{
    int i,j;
    memset(d,127/3,sizeof(d));
    d[s]=0;
    for(i=1; i<=n; i++)
    {
        int temp=getmin();
        v[temp]=1;
        for(j=0; j<e[temp].size(); j++) /**< e[1] 存的是2 4 5,e[1][j] 
        {
            int x=e[temp][j].adj,z=e[temp][j].val;
            if(v[x]==0&&d[x]>d[temp]+z)
            {
                d[x]=d[temp]+z;
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int i,j,x,y,z,ans=0;
    cin>>n>>m;
    for(i=1; i<=m; i++)
    {
        cin>>x>>y>>z;
        e[x].push_back({y,z});
        e[y].push_back({x,z});
    }
    djstra(1);
    if(d[n]<1e8)
        cout<<d[n];
    else
        cout<<-1;
    return 0;
}
*/
/*8649 图的广度遍历
Description
使用图的深度遍历实现的邻接表存储结构和基本操作函数,在此基础上实现图的广度遍历算法并加以测试。注意正确使用队列存储结构。
输入格式
第一行:输入0到3之间整数(有向图:0,有向网:1,无向图:2,无向网:3);
第二行:输入顶点数和边数;
第三行:输入各个顶点的值(字符型,长度〈3);(遍历从输入的第一个顶点开始)
第四行:输入每条弧(边)弧尾和弧头(以空格作为间隔),如果是网还要输入权值;
输出格式
输出对图广度遍历的结果
输入样例
0
3 3
a b c
a b
b c
c b
输出样例
a b c
提示
注意题目的邻接表采用头插法,也就是后出现的边节点插入到邻接表的表头。
*/
#include"string.h"
#include"malloc.h" /* malloc()等 */
#include"stdio.h" /* EOF(=^Z或F6),NULL */
#include"stdlib.h" /* exit() */
#include <queue>

using namespace std;

typedef int InfoType; /* 顶点权值类型 */
#define MAX_NAME 3 /* 顶点字符串的最大长度+1 */
typedef char VertexType[MAX_NAME]; /* 字符串类型 */
/*图的邻接表存储表示 */
#define MAX_VERTEX_NUM 20
typedef enum{DG,DN,AG,AN}GraphKind; /* {有向图,有向网,无向图,无向网} */

typedef struct ArcNode
{
	int adjvex; /* 该弧所指向的顶点的位置 */
	struct ArcNode *nextarc; /* 指向下一条弧的指针 */
	InfoType *info; /* 网的权值指针) */
}ArcNode; /* 表结点 */

typedef struct
{
	VertexType data; /* 顶点信息 */
	ArcNode *firstarc; /* 第一个表结点的地址,指向第一条依附该顶点的弧的指针 */
}VNode,AdjList[MAX_VERTEX_NUM]; /* 头结点 */

typedef struct
{
	AdjList vertices;
	int vexnum,arcnum; /* 图的当前顶点数和弧数 */
	int kind; /* 图的种类标志 */
}ALGraph;

int LocateVex(ALGraph G,VertexType u)
{ /* 初始条件: 图G存在,u和G中顶点有相同特征 */
/* 操作结果: 若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */
	int i;
	for(i=0;i<G.vexnum;++i)
		if(strcmp(u,G.vertices[i].data)==0)
			return i;
	return -1;
}

void CreateGraph(ALGraph *G)
{ /* 采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4种图) */
	int i,j,k;
	int w; /* 权值 */
	VertexType va,vb;
	ArcNode *p;
	//printf("Enter the type of map:(0~3): ");
	scanf("%d",&(*G).kind);
	//printf("Enter Vertex number,Arc number: ");
	scanf("%d%d",&(*G).vexnum,&(*G).arcnum);
	//printf("Enter %d Vertex :\n",(*G).vexnum);
	for(i=0;i<(*G).vexnum;++i) /* 构造顶点向量 */
	{
		scanf("%s",(*G).vertices[i].data);
		(*G).vertices[i].firstarc=NULL;
	}
	//if((*G).kind==1||(*G).kind==3) /* 网 */
	//	printf("Enter order every arc weight,head and tail (Takes the gap by the blank space ):\n");
	//else /* 图 */
	//	printf("Enter order every arc head and tail (Takes the gap by the blank space ):\n");
	for(k=0;k<(*G).arcnum;++k) /* 构造表结点链表 */
	{
		if((*G).kind==1||(*G).kind==3) /* 网 */
		scanf("%d%s%s",&w,va,vb);
		else /* 图 */
		scanf("%s%s",va,vb);
		i=LocateVex(*G,va); /* 弧尾 */
		j=LocateVex(*G,vb); /* 弧头 */
		p=(ArcNode*)malloc(sizeof(ArcNode));
		p->adjvex=j;
		if((*G).kind==1||(*G).kind==3) /* 网 */
		{
			p->info=(int *)malloc(sizeof(int));
			*(p->info)=w;
		}
		else
		p->info=NULL; /* 图 */
		p->nextarc=(*G).vertices[i].firstarc; /* 插在表头 */
		(*G).vertices[i].firstarc=p;
		if((*G).kind>=2) /* 无向图或网,产生第二个表结点 */
		{
			p=(ArcNode*)malloc(sizeof(ArcNode));
			p->adjvex=i;
			if((*G).kind==3) /* 无向网 */
			{
				p->info=(int*)malloc(sizeof(int));
				*(p->info)=w;
			}
			else
			p->info=NULL; /* 无向图 */
			p->nextarc=(*G).vertices[j].firstarc; /* 插在表头 */
			(*G).vertices[j].firstarc=p;
		}
	}
}

VertexType* GetVex(ALGraph G,int v)
{ /* 初始条件: 图G存在,v是G中某个顶点的序号。操作结果: 返回v的值 */
	if(v>=G.vexnum||v<0)
		exit(0);
	return &G.vertices[v].data;
}

int FirstAdjVex(ALGraph G,VertexType v)
{ /* 初始条件: 图G存在,v是G中某个顶点 */
/* 操作结果: 返回v的第一个邻接顶点的序号。若顶点在G中没有邻接顶点,则返回-1 */
	ArcNode *p;
	int v1;
	v1=LocateVex(G,v); /* v1为顶点v在图G中的序号 */
	p=G.vertices[v1].firstarc;
	if(p)
		return p->adjvex;
	else
		return -1;
}

int NextAdjVex(ALGraph G,VertexType v,VertexType w)
{ /* 初始条件: 图G存在,v是G中某个顶点,w是v的邻接顶点 */
/* 操作结果: 返回v的(相对于w的)下一个邻接顶点的序号。 */
/* 若w是v的最后一个邻接点,则返回-1 */
	ArcNode *p;
	int v1,w1;
	v1=LocateVex(G,v); /* v1为顶点v在图G中的序号 */
	w1=LocateVex(G,w); /* w1为顶点w在图G中的序号 */
	p=G.vertices[v1].firstarc;
	while(p&&p->adjvex!=w1) /* 指针p不空且所指表结点不是w */
		p=p->nextarc;
	if(!p||!p->nextarc) /* 没找到w或w是最后一个邻接点 */
		return -1;
	else /* p->adjvex==w */
		return p->nextarc->adjvex; /* 返回v的(相对于w的)下一个邻接顶点的序号 */
}

int visited[MAX_VERTEX_NUM]; /* 访问标志数组(全局量),未访问标记0,访问标记1 */
void(*VisitFunc)(char* v); /* 函数变量(全局量) */

void BFSTraverse(ALGraph G,void(*Visit)(char*)) //广搜
{
    int v;
    VisitFunc=Visit;
	queue<int> Q;
    memset(visited,0,sizeof(visited));
    for(v=0;v<G.vexnum;++v)
    {
    	if(!visited[v])
    	{
    		visited[v]=1;
			Q.push(v);
			VisitFunc(G.vertices[v].data);
    		while(!Q.empty())
    		{
    			int t,w;
    			t=Q.front();
    			Q.pop();
    			for(w=FirstAdjVex(G,G.vertices[t].data);w>=0;w=NextAdjVex(G,G.vertices[t].data,G.vertices[w].data))
    			{
    				if(!visited[w])
    				{
    					visited[w]=1;
    					VisitFunc(G.vertices[w].data);
    					Q.push(w);
    				}
    			}
    		}
    	}
    }
	printf("\n");
}

void print(char *i)
{
	printf("%s ",i);
}

int main()
{
	ALGraph g;
	CreateGraph(&g);
	BFSTraverse(g,print);
	return 1;
}

/*18734 拓扑排序
在经历.....之后,你打算好好学习下计算机专业的课程,避免面试过程中的各种尴尬场面。
计算机的专业课程间既有循序渐进的特点,相互间也存在着依赖关系(似乎其他专业也是这样......)。
现在给你n门课程和m个课程间关系,请给出一个有效的学习次序。
注意可能存在多门课程不依赖任何其他课程
输入格式
第一行有2个数,分别为课程数n和关系数m。     (1=<n<=20) (1=<m<=30)
接下来有m行,每一行有2个整数a和b,表示课程b依赖于课程a。(1=<a,b<=n)
输出格式
仅一行,一个整数序列,代表课程学习次序。
为确保输出唯一性,同等条件下,编号小的在排在前面。
输入样例
6 8
1 2
1 3
1 4
3 2
3 5
4 5
6 4
6 5
输出样例
1 3 2 6 4 5*/

#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
vector<int> v[30];
int a[30],c[30];
int main()
{
    int n,m,cnt=0;
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        v[x].push_back(y);
        a[y]++;
    }
    priority_queue<int,vector<int>,greater<int> >q;
    for(int i=1;i<=n;i++)
    {
        if(!a[i])
            q.push(i);
    }
    while(!q.empty())
    {
        int x=q.top();
        q.pop();
        for(int i=0;i<v[x].size();i++)
        {
            a[v[x][i]]--;
            if(!a[v[x][i]])
                q.push(v[x][i]);
        }
        c[++cnt]=x;
    }
    for(int i=1;i<=cnt;i++)cout<<c[i]<<" ";
    return 0;
}

/*#include <bits/stdc++.h>
typedef long long ll;
using namespace std;

int main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int i,j,n,m,a[25][25]= {0},d[105]= {0},x,y;
    cin>>n>>m;
    for(i=1; i<=m; i++)
    {
        cin>>x>>y;
        a[x][y]=1;
        d[y]++;
    }
    set<int>st;
    for(i=1; i<=n; i++)
        if(d[i]==0)
            st.insert(i);
    while(!st.empty())
    {
        int t=*st.begin();
        cout<<t<<' ';
        st.erase(st.begin());
        for(i=1; i<=n; i++)
        {
            if(a[t][i])
            {
                d[i]--;
                if(d[i]==0)
                    st.insert(i);
            }
        }
    }
    return 0;
}
*/


/*18747 关键路径
Description
在一个工程项目里,多项工作可以同时进行。
我们可以用有向无环图表述项目流程,把项目中的事件表述为结点,把活动表述成有权值的边。
现在我们已知项目共有n个事件,起点为1,终点为n,m个活动。
请你计算出这个项目的最早完成时间,也就是起点到收点的最长路径,即关键路径。
输入格式
第一行两个整数n和m,代表结点数量和边数量。(1<=n,m<=100)
下面m行,每行3个整数a,b,x,表示点a到点b之间有一条长度为x的有向边。
输出格式
一个整数,起点到终点的最长路径.
输入样例
4 6
1 2 3
1 3 2
1 4 3
2 3 3
2 4 5
3 4 3
输出样例
9*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>

using namespace std;

int n,m,d[1005]= {0},e[1005][1005],dp[1005]; //dp动态规划

int main()
{
    cin >> n >> m;
    int i,x,y,z;
    for(i=1; i<=m; i++)
    {
        cin >> x >> y >> z;
        e[x][y]=z;//构建邻接矩阵,赋权值
        d[y]++;//入度数+1
    }
    queue<int>q;
    for(i=1; i<=n; i++)
    {
        if(d[i]==0)//如果入度数为0
            q.push(i);//入队
    }
    while(q.size())
    {
        int t=q.front();//取队头元素
        //cout << t << ' ';
        q.pop();//弹出
        for(i=1; i<=n; i++) //n个顶点
        {
            if(e[t][i])
            {
                dp[i]=max(dp[i],dp[t]+e[t][i]);//求从点1到点i的最长路径
                d[i]--;//入度数-1
                if(d[i]==0)//如果入度数为0
                    q.push(i);//入队
            }
        }
    }
    cout << dp[n];//输出从起点1到终点n的最长路径
    return 0;
}

/*
标程

#include <iostream>
#include <queue>
using namespace std;
int n,m,a[105][105],v[1005],d[1005],dis[1005];
int main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int i,j,x,y,z;
    cin>>n>>m;
    for(i=1; i<=m; i++)
    {
        cin>>x>>y>>z;
        a[x][y]=z;
        d[y]++;
    }
    queue<int>q;
    q.push(1);
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        for(i=1; i<=n; i++)
        {
            if(a[t][i])
            {
                d[i]--,dis[i]=max(dis[i],dis[t]+a[t][i]);
                if(d[i]==0)
                    q.push(i);
            }
        }
    }
    cout<<dis[n];
    return 0;
}
*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值