6.16 NOIp2019 第三次模拟赛 订正总结

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

Thinking process

  • 2:30拿题,半个小时看题,设计算法。
  • 写题经历:
    • T 1 T1 的想法经历:刚开始想打 t a r j a n tarjan ,然后没想到最后的反向 T o p s o r t Topsort 处理,挂掉。跑去写 T 2 T2 ,然后最后想到一个算法,那就是跑 n n d f s dfs ,看这个节点是否能遍历到 n 1 n-1 个其他的节点,能的话加入答案集合,否则不管。哈,能 A A 了,结果因为没有清零 v i s [ i ] vis[i] 挂成 30 30 ,呜~。
    • T 2 T2 的想法经历:可持久化 T r i e Trie 树?完了,不会写啊,诶,好像不是,这不是连续区间。然后有些想写最大流,因为看到了比赛分配。离考试结束还有半小时的时候,看着画的图,心想:这不是个生成树?去,慌得我赶紧改。心想可以 A A 了,结果数组开小见祖宗。被爆成 30 30
    • T 3 T3 的想法经历:其实是最不认真的一道,直接写了那个 O ( n 2 m ) O(n^2m) 的算法,没想到却成了唯一一道 A A 掉的题目。
  • 评测结果:得分 160 160 ,排名第 7 7 ,被卡到中间了,真菜。
  • 一些感想:和 C h d y Chdy 谈了会儿,的确是有学的多的原因,但是,我想,若是我全部理解,即使写了那种高级算法,也是能 A A 掉的,所以其实归根结底还是我对 c o d e code 的理解程度不够,所以要在这点下功夫。

流图

title

在这里插入图片描述

analysis

在这里插入图片描述
对,就这么简单呵呵,我 v i s [ i ] vis[i] 忘清零,我说什么了?真是笨

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1, ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}

template<typename T>inline void write(T x)
{
	if (!x) { putchar('0'); return ; }
	if (x<0) putchar('-'), x=-x;
	T num=0, ch[20];
	while (x) ch[++num]=x%10+48, x/=10;
	while (num) putchar(ch[num--]);
}

int ver[maxn],Next[maxn],head[maxn],len;
inline void add(int x,int y)
{
	ver[++len]=y,Next[len]=head[x],head[x]=len;
}

int tot;
bool vis[maxn];
inline void dfs(int x)
{
	vis[x]=1;
	for (int i=head[x]; i; i=Next[i])
	{
		int y=ver[i];
		if (!vis[y]) ++tot,dfs(y);
	}
}

int ans[maxn],cnt;
int main()
{
	freopen("flow.in","r",stdin);
	freopen("flow.out","w",stdout);
	int n,m;read(n);read(m);
	for (int i=1,x,y; i<=m; ++i) read(x),read(y),add(x,y);
	for (int i=1; i<=n; ++i)
	{
		memset(vis,0,sizeof(vis));//记得清零
		tot=0;
		dfs(i);
		if (tot==n-1) ans[++cnt]=i;
	}

	write(cnt),puts("");
	for (int i=1; i<=cnt; ++i) write(ans[i]),putchar(' ');
	return 0;
}

足球锦标赛

title

BZOJ 3943
在这里插入图片描述

analysis

在这里插入图片描述
哈哈,我的思路:
最开始:可持久化 T r i e Trie 树?完了,不会写啊,诶,好像不是。
然后:有些想写最大流。
离考试结束还有半小时:这不是个生成树?去,慌得我赶紧改。
所以,我太sb了。

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e3+10;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1, ch=getc();
	while (!isdigit(ch) && ch^'-') ch=getc();
	if (ch=='-') f=-1, ch=getc();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getc();
	x*=f;
}

template<typename T>inline void write(T x)
{
	if (!x) { putchar('0'); return ; }
	if (x<0) putchar('-'), x=-x;
	T num=0, ch[20];
	while (x) ch[++num]=x%10+48, x/=10;
	while (num) putchar(ch[num--]);
}

struct Orz{int x,y; ll z;}e[maxn*maxn];
int fa[maxn],a[maxn];
inline int get(int x)
{
	return fa[x]==x?x:fa[x]=get(fa[x]);
}

inline bool cmp(Orz a,Orz b)
{
	return a.z>b.z;
}

int main()
{
	freopen("bull.in","r",stdin);
	freopen("bull.out","w",stdout);
    int n,cnt=0,tot=0;read(n);
    for (int i=1; i<=n; ++i)
    {
        fa[i]=i;read(a[i]);
        for (int j=1; j<i; ++j) e[++cnt].x=j,e[cnt].y=i,e[cnt].z=a[i]^a[j];
    }
    sort(e+1,e+cnt+1,cmp);
    ll ans=0;
    for (int i=1; i<=cnt; ++i)
    {
        int x=get(e[i].x),y=get(e[i].y);
        if (x==y) continue;
        fa[x]=y;
        ans+=e[i].z;
        ++tot;
        if (tot==n-1) break;
    }
    write(ans);
    return 0;
}

奶牛派对

title

在这里插入图片描述

analysis

在这里插入图片描述
我的暴力算法是跑了 n n S P F A SPFA ,刚写完的时候,因为这是个最坏 O ( N 2 M ) O(N^2M) 复杂度的算法,便对自己说,哎,拿不了满分了,然而没想到数据水的让我感动。

code

暴力算法

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10,maxm=1e4+10;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1, ch=getc();
	while (!isdigit(ch) && ch^'-') ch=getc();
	if (ch=='-') f=-1, ch=getc();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getc();
	x*=f;
}

template<typename T>inline void write(T x)
{
	if (!x) { putchar('0'); return ; }
	if (x<0) putchar('-'), x=-x;
	T num=0, ch[20];
	while (x) ch[++num]=x%10+48, x/=10;
	while (num) putchar(ch[num--]);
}

int ver[maxm],edge[maxm],Next[maxm],head[maxn],len;
inline void add(int x,int y,int z)
{
	ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}

int dist[maxn],num[maxn];
bool vis[maxn];
inline void spfa(int s)
{
	memset(dist,0x3f,sizeof(dist));
	memset(vis,0,sizeof(vis));
	queue<int>q;q.push(s);
	dist[s]=0,vis[s]=1;
	while (!q.empty())
	{
		int x=q.front();
		q.pop();
		vis[x]=0;
		for (int i=head[x]; i; i=Next[i])
		{
			int y=ver[i],z=edge[i];
			if (dist[y]>dist[x]+z)
			{
				dist[y]=dist[x]+z;
				if (!vis[y]) q.push(y),vis[y]=1;
			}
		}
	}
}

int main()
{
	freopen("party.in","r",stdin);
	freopen("party.out","w",stdout);
	int n,m,p,ans=0;
	read(n);read(m);read(p);
	for (int i=1,x,y,z; i<=m; ++i) read(x),read(y),read(z),add(x,y,z);
	for (int i=1; i<=n; ++i)
		if (i!=p) spfa(i),num[i]=dist[p];
	spfa(p);
	for (int i=1; i<=n; ++i) ans=max(ans,dist[i]+num[i]);
	write(ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/92423197