给定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;
}