我是早上T3唯一AC的人,大家来帮忙看看正确性
  • 板块学术版
  • 楼主h7373
  • 当前回复29
  • 已保存回复29
  • 发布时间2022/11/19 16:01
  • 上次更新2023/10/27 02:22:19
查看原帖
我是早上T3唯一AC的人,大家来帮忙看看正确性
359755
h7373楼主2022/11/19 16:01

RT,现在我的做法是各方面碾了标算,大家来看看到底是算法假加数据水还是这个题本身就可以这么做。

思路:由于始终存在一条 1>n1->n 的路径,考虑保这条路径。

考虑所有路径按照询问来说最晚不连通的那条,显然我们保证这条不被删即可。

于是按照询问时间戳给边定权,不被询问的边认为无限大(可以认为这些边都在询问的边之后被删掉)。多次询问的边以第一次为准。(显然第二次即之后的询问都是无效的,第一次被删之后就没法删;第一次不被删之后也一定不能被删)

找一条路径,使其经过的边最小边权最大,这条路径就不会被删。

这样可以离线解决本题。下帖代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=0x7f7f7f7f;
const int maxn=2e5;
bool flag[maxn+5];
int fr[maxn+5],to[maxn+5],nex[maxn+5],lk[maxn+5],w[maxn+5],M=0;
int coming[maxn+5];
int ask[maxn+5];
int fst[maxn+5];
bool ans[maxn+5];
struct road{
	int v,id,w;
	bool operator < (const road &x) const
	{
		return w<x.w;
	}
};
priority_queue<road,vector<road> , less<road> > Q;
void solve(int n)
{
	road item,tp;
	item.v=1;item.w=INF;item.id=INF;Q.push(item);
	for (int i=1;i<=n;i++) flag[i]=false;
	while(!Q.empty())
	{
		tp=Q.top();
		Q.pop();
		if (flag[tp.v]) continue;
		flag[tp.v]=true;
		coming[tp.v]=tp.id;
		for (int i=lk[tp.v];i>0;i=nex[i])
		{
			if (!flag[to[i]])
			{
				item.v=to[i];
				item.id=i;
				item.w=w[i];
				Q.push(item);
			}
		}
	}
	int p=n;
	while(coming[p]<INF)
	{
		if (w[coming[p]]<INF)
			ans[w[coming[p]]]=true;
		p=fr[coming[p]];
	}
	return ;
}
int main()
{
	int n,m,q,u,v;
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=n;i++) lk[i]=-1,coming[i]=INF;
	for (int i=1;i<=m;i++) {
		scanf("%d%d",&u,&v);
		fr[i]=u;to[i]=v;nex[i]=lk[u];lk[u]=i;w[i]=INF;
	}
	for (int i=1;i<=q;i++)
	{
		scanf("%d",&ask[i]);
		w[ask[i]]=min(w[ask[i]],i);
		ans[i]=false;
	}
	solve(n);
	for (int i=1;i<=q;i++)
	{
		if (ans[i]||i!=w[ask[i]]) puts("0");
		else puts("1");
	}
	return 0;
}

代码应该还是不丑的。大家有时间愿意帮忙的话就来看看有没有问题吧。若有问题给个hack啥的,谢谢大家了。

2022/11/19 16:01
加载中...