616

在这里插入图片描述
还是自己菜的一批。。。

流图

【题目描述】
如果一张有向图存在一个点可以到达所有的点,则称这个图是一个流图(Flow Graph)。
现在给定一张有向图,请判断这张图是不是流图;如果是,输出所有的点r满足点r可以到达图中的所有点。
【数据输入】
第一行两个正整数n和m,分别表示这张图的点数和边数。 接下来m行,每行两个正整数x,y (1<=x,y<=n),表示一条从x到y的有向边。
【数据输出】
如果这张图不是流图,输出“0”(不含引号); 否则,第一行输出满足条件的点r的个数,第二行按升序输出这r个点。
【样例输入】
3 3
1
2
2
1
1
3
【样例输出】
2
1 2
【数据范围】
对于20%的数据,n,m<=10 对于50%的数据,n,m<=100
对于100%的数据,n,m<=1000

思路

因为这道题的数据范围不是很大,所以我们可以直接暴力解决。
有两个思路:

  1. 枚举每个点,DFS一遍判断能不能到达所有点就行了。(题解)
  2. Floyd,最后枚举每一个点,判断是否能到达所有的点。(abibats的思路)

对于这道题,我只得到了20分。
错因:对于flow是由于没有考虑自环的影响。

code

DFS

#include<bits/stdc++.h>
using namespace std;

const int nn=1006;

int n,m;
bool f[nn][nn];
int ans[nn];
int cnt=0;

inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
	return x*f;
}

bool dfs(int x,int sum)
{
	if(sum==n-1)	return true;
	for(int i=1;i<=n;++i)
	{
		if(i==x)	continue;
		if(f[x][i]&&dfs(i,sum+1))	return true;
	}
	return false;
}

int main()
{
	n=read(); m=read();
	for(int i=1;i<=m;++i)
	{
		int a=read();
		int b=read();
		f[a][b]=true;
	}
	
	for(int i=1;i<=n;++i)
		if(dfs(i,0))
			ans[++cnt]=i;
	
	if(cnt==0)
	{
		printf("0");
		return 0;
	}
	printf("%d\n",cnt);
	for(int i=1;i<=cnt;++i)
		printf("%d ",ans[i]);
	return 0;
}

Floyd

#include<bits/stdc++.h>
using namespace std;

const int nn=1006;

int n,m;
bool f[nn][nn];
int ans[nn];

inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
	return x*f;
}

int main()
{
	freopen("flow.in","r",stdin);
	freopen("flow.out","w",stdout);
	
	n=read(); m=read();
	for(int i=1;i<=m;++i)
	{
		int a=read();
		int b=read();
		f[a][b]=true;
	}
	
	for(int k=1;k<=n;++k)
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
				if(!f[i][j]&&f[i][k]&&f[k][j])
					f[i][j]=true;
	
	int cnt=0;
	for(int i=1;i<=n;++i)
	{
		bool flag=true;
		for(int j=1;j<=n;++j)
		{
			if(j==i)	continue;
			if(!f[i][j])	flag=false;
		}
		if(flag)	ans[++cnt]=i;
	}
	
	if(cnt==0)
	{
		printf("0");
		return 0;
	}
	printf("%d\n",cnt);
	for(int i=1;i<=cnt;++i)
		printf("%d ",ans[i]);
	return 0;
}

足球锦标赛

【题目描述】
贝西和她的朋友们在参加一年一度的足球锦标赛。FJ的任务是让这场锦标赛尽可能地好看。
一共有N支球队参加这场比赛,每支球队都有一个取值在1~2^30-1之间的整数编号。
足球锦标赛是一个淘汰赛制的比赛——每场比赛过后,FJ选择一支球队淘汰,淘汰了的球队将不能再参加比赛。
锦标赛在只有一支球队留下的时候就结束了。
FJ发现了一个神奇的规律:在任意一场比赛中,这场比赛的得分是参加比赛两队的编号的异或(Xor)值。例如:编号为12的队伍和编号为20的队伍之间的比赛的得分是24分,因为 12(01100) Xor 20(10100) = 24(11000)。
FJ相信比赛的得分越高,比赛就越好看,因此,他希望安排一个比赛顺序,使得所有比赛的得分和最高。请帮助FJ决定比赛的顺序。
【数据输入】
第一行一个正整数N,代表球队的数量。
接下来N行,第i行1个正整数,代表第i支球队的编号。
【数据输出】
一行一个非负整数,表示所有比赛得分之和的最大值。
【样例输入】
4
3
6
9
10
【样例输出】
37
【数据范围】
对于30%的数据,n<=5
对于60%的数据,n<=100
对于100%的数据,n<=2000

思路

容易发现这个题就是求个最大生成树,两点间的边权等于编号的异或值,用Kruskal或者Prim算法都能通过此题----题解

这道题我拿到了10分。
错因
思路错误。
假如说你排序的答案是:$ xor b,b xor c,c xor a.那么这三个就都会用上,而没有剔除出去的。(因为剔除出去的一定是参加比赛的。)
而且,数据范围,1E9,记得longlong
对于Kruskal,要考虑边的起点和终点。

code

#include<bits/stdc++.h>
using namespace std;

const int nn=2010;
typedef long long ll;

int n;
int a[nn];
ll fa[nn];
int cnt=0;
ll ans=0;
struct number
{
	int x,y;
	ll z;
}num[nn];

inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
	return x*f;
}

bool mycmp(number x,number y)
{
	return x.z>y.z;
}

int gf(int x)
{
	if(x==fa[x])	return x;
	return fa[x]=gf(fa[x]);
}

int main()
{
	freopen("bull.in","r",stdin);
	freopen("bull.out","w",stdout);
	
	n=read();
	for(int i=1;i<=n;++i)	a[i]=read(),fa[i]=i;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
		{
			num[++cnt].x=i;
			num[cnt].y=j;
			num[cnt].z=(ll)a[i]^a[j];
		}
		
	sort(num+1,num+1+cnt,mycmp);
	
	for(int i=1;i<=cnt;++i)
	{
		ll xx=gf(num[i].x);
		ll yy=gf(num[i].y);
		if(xx==yy)	continue;
		fa[xx]=yy;
		ans+=num[i].z;
	}
	
	printf("%lld\n",ans);
	return 0;
}

奶牛派对

【题目描述】
有N个农场,编号为1到N,用M条单向道路连接,其中通过第i条道路所需的时间是Ti。
现在所有农场中的牛都要走到X号农场(1<=X<=N)开派对,并在派对后返回自己的农场。当然,去的路和回来的路可能不同,因为路是单向的。
每头牛都很懒,他们会选择消耗时间总和最短的路径来走。求所有牛在路上花费的时间的最大值。
【数据输入】
第一行三个正整数N,M,X,含义如题所示。
接下来M行,第i行有三个正整数Ai,Bi,Ti,代表沿着第i条道路可以从Ai走到Bi,耗时为Ti。
【数据输出】
输出一行一个正整数,代表所有牛在路上花费的时间的最大值。
【样例输入】
4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3
【样例输出】
10
【数据范围】
对于30%的数据,n<=8,m<=40
对于60%的数据,n<=100,m<=1000
对于100%的数据,n<=1000,m<=10000,1<=Ti<=100

思路

  1. 对于每个点我们要求出这个点到点X再回来的最短路,点X到这个点的最短路只需要跑一遍以点X为源点的Dijkstra就行了,但是每个点到点X的最短路怎么求呢?把边反向之后再跑一遍以点X为源点的Dijkstra就行了。(题解)
  2. Floyd(自己当时敲得代码,然后过了,因为数据范围比较小)

这是唯一 一道自己A掉了的。于是乎,就没有敲题解上的代码。

code

#include<bits/stdc++.h>
using namespace std;

const int nn=1010;

int n,m,g;
int f[nn][nn];
int ans=0;

inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
	return x*f;
}

int main()
{
	freopen("party.in","r",stdin);
	freopen("party.out","w",stdout);
	n=read(); m=read(); g=read();
	memset(f,0x3f3f3f,sizeof(f));
	for(int i=1;i<=m;++i)
	{
		int a=read();
		int b=read();
		int c=read();
		f[a][b]=min(f[a][b],c);
	}
	
	for(int k=1;k<=n;++k)
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
				if(f[i][k]+f[k][j]<f[i][j])
					f[i][j]=f[i][k]+f[k][j];
	for(int i=1;i<=n;++i)
	{
		if(i==g)	continue;
		int sum=f[i][g]+f[g][i];
		ans=max(ans,sum);
	}
	
	printf("%d\n",ans);
	return 0;
}

都不能确定以后去哪里 明天发生哪些事 运气如何 会不会和谁拥抱啊 天空出现什么形状的云朵 不小心跌倒的事情也会有吧 但是已经知道了过去 现在 在这些时间里 确定爱谁了吗 还是爱自己 去吃美味的食物 也要克制食欲 要去追逐梦想 也要偶尔停下脚步一下 有人一起走的话 就手拉着手跑起来吧 一个人 也不要沮丧 先试试自己到底能去多远 只要你说生活是好的 它就是好的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值