还是自己菜的一批。。。
流图
【题目描述】
如果一张有向图存在一个点可以到达所有的点,则称这个图是一个流图(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
思路
因为这道题的数据范围不是很大,所以我们可以直接暴力解决。
有两个思路:
- 枚举每个点,DFS一遍判断能不能到达所有点就行了。(题解)
- 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
思路
- 对于每个点我们要求出这个点到点X再回来的最短路,点X到这个点的最短路只需要跑一遍以点X为源点的Dijkstra就行了,但是每个点到点X的最短路怎么求呢?把边反向之后再跑一遍以点X为源点的Dijkstra就行了。(题解)
- 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;
}
都不能确定以后去哪里 明天发生哪些事 运气如何 会不会和谁拥抱啊 天空出现什么形状的云朵 不小心跌倒的事情也会有吧 但是已经知道了过去 现在 在这些时间里 确定爱谁了吗 还是爱自己 去吃美味的食物 也要克制食欲 要去追逐梦想 也要偶尔停下脚步一下 有人一起走的话 就手拉着手跑起来吧 一个人 也不要沮丧 先试试自己到底能去多远 只要你说生活是好的 它就是好的