补图
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
题目给出一个无向图,求该无向图关于完全图的相对补图,并求该补图的最大度和最小度。方便起见,用邻接矩阵表示该无向图。无向图的节点数不少于2并且不超过500.
Input
多组输入,每组输入第一行是无向图中节点的数量即邻接矩阵的行列数n。接下来n行n列为该图的邻接矩阵。
Output
每组数据,首先输出n行n列表示补图的邻接矩阵。接下来一行两个用空格分隔的整数,分别代表补图的最大度和最小度。
Sample Input
4
0 0 1 1
0 0 0 1
1 0 0 0
1 1 0 0
Sample Output
0 1 0 0
1 0 1 0
0 1 0 1
0 0 1 0
2 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int a[505][505],b[505][505];
int main()
{
int n,i,j,gas,max,min;
while(scanf("%d",&n)!=EOF)
{
max=0;
min=505;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
scanf("%d",&a[i][j]);
if(i!=j)
{
if(a[i][j]==0)
b[i][j]=1;
else
b[i][j]=0;
}
}
}
for(i=0; i<n; i++)
{
gas=0;
for(j=0; j<n; j++)
{
if(b[i][j]==1)gas++;
}
if(max<gas)max=gas;
if(min>gas)min=gas;
}
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
if(j!=n-1)printf("%d ",b[i][j]);
else printf("%d\n",b[i][j]);
}
}
printf("%d %d\n",max,min);
}
return 0;
}
指定长度路径数
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
题目给出一个有n个节点的有向图,求该有向图中长度为k的路径条数。方便起见,节点编号为1,2,…,n,用邻接矩阵表示该有向图。该有向图的节点数不少于2并且不超过500.
例如包含两个节点的有向图,图中有两条边1 → 2 ,2 → 1 。
长度为1的路径有两条:1 → 2 和 2 →1 ;
长度为2的路径有两条:1 → 2 → 1和2 → 1 → 2 ;
偷偷告诉你也无妨,其实这个图无论k取值多少 ( k > 0 ),长度为k的路径都是2条。
Input
多组输入,每组输入第一行是有向图中节点的数量即邻接矩阵的行列数n。接下来n行n列为该图的邻接矩阵。接下来一行是一个整数k.k小于30.
Output
输出一个整数,即为图中长度为k的路径的条数。
Sample Input
3 0 1 0 0 0 1 0 0 0 2
Sample Output
1
/*在有向图中,如果需要求vi到vj的长度为x的通路数,
只需要对矩阵A进行x次乘法即可,然后矩阵中a[i]][j]就是
vi到vj长度为x的通路数量,其中回路数量是a[i][i],然
后在计算机中怎么表示呢,求矩阵的n次幂需要3个数组,
一个作为a的x次幂的空白矩阵,另外两个一个存原来的矩阵即A本身
,另外一个矩阵存上一次幂的矩阵,这两个矩阵再存到空白矩
阵去,反复这样可以求出A的x次幂的矩阵*/
//以上是其他博主经验
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int n;
int ia[1105][1105];
int image[1005][1005];
int b[1005][1005];
int main()
{
int i,j,o,k;
while(scanf("%d",&n)!=EOF)
{
memset(image,0,sizeof(image));
memset(b,0,sizeof(b));
for(i=1; i<=n; i++)
{
for( j=1; j<=n; j++)
{
scanf("%d",&image[i][j]);
}
}
for( i=1; i<=n; i++)
{
for( j=1; j<=n; j++)
{
ia[i][j]=image[i][j];
}
}
int q;
scanf("%d",&q);
int count=0;
for( o=2; o<=q; o++)
{
for( i=1; i<=n; i++)
{
for( j=1; j<=n; j++)
{
for( k=1; k<=n; k++)
{
b[i][j]+=ia[i][k]*image[k][j];
}
}
}
for( i=1; i<=n; i++)
{
for( j=1; j<=n; j++)
image[i][j]=b[i][j];
}
if(o!=q)
memset(b,0,sizeof(b));
}
for( i=1; i<=n; i++)
{
for( j=1; j<=n; j++)
{
if(b[i][j])
count+=b[i][j];
}
}
printf("%d\n",count);
}
return 0;
}
建图
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
编程使得程序可以接受一个图的点边作为输入,然后显示出这个图。
Input
多组测试数据,对于每组测试数据,第一行输入正整数n(1 <= n <= 1000)和m,之后m行输入正整数x、y,表示在点x和点y之间存在有向边相连。
Output
对于每组测试数据,输出图的关系矩阵。
Sample Input
4 5 1 1 2 2 2 4 3 3 4 4
Sample Output
1 0 0 0 0 1 0 1 0 0 1 0 0 0 0 1
#include <stdio.h>
#include <string.h>
int main()
{
int m,i,g,j,a1,a2;
int a[1001][1001];
while (scanf("%d%d",&m,&g)!=EOF)
{
memset(a,0,sizeof(a));
for (i=1;i<=g;i++)
{
scanf("%d%d",&a1,&a2);
a[a1][a2]=1;
}
for (i=1;i<=m;i++)
{
for (j=1;j<=m;j++)
{
if (j==1)printf("%d",a[i][j]);
else printf(" %d",a[i][j]);
}
printf("\n");
}
}
return 0;
}
/***************************************************
User name:
Result: Accepted
Take time: 132ms
Take Memory: 2020KB
Submit time: 2019-06-06 10:30:32
****************************************************/
最小生成树
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
在一个无向图中,求最小生成树。
Input
多组测试数据,对于每组测试数据,第1行输入正整数n(1 <= n <= 1000)、m,表示n个顶点(编号从1开始)和m条边。之后m行每行输入u(1 <= u <= n)、v(1 <= v <= n)、w(1 <= w <= 100),表示在顶点u和顶点v之间存在无向边,且权值为w。
Output
对于每组测试数据,若存在最小生成树则输出最小生成树的权值和,若不存在最小生成树则输出-1。
Sample Input
3 7 1 2 19 2 3 11 3 1 7 1 3 5 2 3 89 3 1 91 1 2 32
Sample Output
16
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define INF 0x3f3f3f3f
int n,m;
int mp[1100][1100],dis[1100],vis[1100];
int sum;
void f(int s)
{
int i,j;
for(i=1;i<=n;i++)
{
dis[i]=mp[s][i];
vis[i]=0;
}
dis[s]=0;
vis[s]=1;
for(i=1;i<=n-1;i++)
{
int minn=INF;
int u;
for(j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]<minn)
{
minn=dis[j];
u=j;
}
}
if(minn==INF)
{
printf("-1\n");
return ;
}
vis[u]=1;
sum+=minn;
for(j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]>mp[u][j])
{
dis[j]=mp[u][j];
}
}
}
printf("%d\n",sum);
}
int main ()
{
int i,j,u,v,w;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==j)
mp[i][j]=0;
else
mp[i][j]=INF;
}
}
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
if(mp[u][v]>w)
{
mp[u][v]=mp[v][u]=w;
}
}
sum=0;
f(1);
}
return 0;
}
/***************************************************
User name:
Result: Accepted
Take time: 84ms
Take Memory: 2420KB
Submit time: 2019-06-20 10:13:01
****************************************************/