C++:邻接矩阵存图

给定n个点, m条单向边  n<=1000, m <= 100000

有k个询问,询问x出去的所有边及其权值,如果有多条边,终点编号小的先输出,具体见样例


输入格式(Format Input)

第一行输入两个整数n和m,表示有n个点和m条边。 接下来输入m行,每行三个整数x y z,表示x到y有一条权值为z的单向边。如果两个点之间有多条边,保留权值最小的一条。 输入一个数字k,表示有k个询问(k<=n)。 接下来输入k行,每行输入一个整数x(x表示节点编号)。

输出格式(Format Output)

对于每一个询问x,输入与x相连的边,每条边占一行,对于每条边先输出终点编号,再输出边权,中间用空格隔开。


输入样例(Sample Input) 

4 5

1 2 5

1 3 4

2 4 3

1 4 8 1 3 3

2

2

输出样例(Sample Output)

2 5 3 3 4 8 4 3

前项星写法:

#include<bits/stdc++.h>
using namespace std;
int n,m,k,cnt=0;//cnt表示第i条边,默认为0。 k:几组查询 
int last[1010];//last[i]代表i后的第一个边。
int nxt[1010];//nxt[i]代表第i条边的下一条边。
int w[1010];//w[i]代表第i条边的权值。
int ed[1010];//ed[i]表示第i条边的“终点”。
void edge(int x,int y,int z)//新增一条从x至y,边权为z的边。
{
    cnt++;//此乃第i条边!
    ed[cnt]=y,w[cnt]=z;//i条边终点为y,边权为z。
    //前插法 将数据从“头 ”插入 。 
    nxt[cnt]=last[x];//i的下一条边为第x(起点)点后的第一条边。 
    last[x]=cnt;//x(起点)点后的第一条边为第i条边。 
    //注意!先让i的下一条边为第x(起点)点后的第一条边,再让x(起点)点后的第一条边为第i条边。这样才不会将图“断掉 ”。 
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        cin>>x>>y>>z;
        edge(x,y,z);//新增一条从x至y,边权为z的边。 
    }
    cin>>k;
    for(int i=1;i<=k;i++)
    {
        int x;
        cin>>x;//键入要查询的节点。 
        for(int j=last[x];j;j=nxt[j])	//设j为 x后的第一条边。如果j!=0,就一直运行。这遍循环后,j来到j+1条边。 
        {
            cout<<ed[j]<<" "<<w[j]<<endl;	//输出终点与边权。 
        }
    }
    return 0;
}

但由于本人太菜了?,只会前插法,所以还是用暴力点的法子吧。这法子存储的是点,上边的是边。

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int g[1001][1001];
int main()
{
    cin>>n>>m;
    memset(g,-1,sizeof(g));//初始值全列为-1,由于本体无负权边,so,无伤大雅。
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        cin>>x>>y>>z;
        if(g[x][y]==-1) g[x][y]=z;//如果直接min,g[x][y]永远为-1,so,特判一下。
        else g[x][y]=min(g[x][y],z);
    }
    cin>>k;
    for(int i=1;i<=k;i++)
    {
        int x;
        cin>>x;
        for(int j=1;j<=n;j++)//快乐地循环n次。
        {
            if(g[x][j]!=-1)//有边权!!!
            {
                cout<<j<<" "<<g[x][j]<<endl;//快乐地输出
            }
        }
    }
    return 0;
}
上一篇
下一篇