CF1515F Phoenix and Earthquake
CF1515F Phoenix and Earthquake
证明题。
思路
考虑不合法的情况,如果
再考虑对于一个可行的情况,最后缩的边肯定形成一棵树,所以我们大胆假设:任意一棵生成树只要满足
考虑归纳证明:
在
-
若
,那么我们删除 这条边,由于所需总和 减少了 ,而 减少了 ,所以归纳假设任然成立。将边 加入栈。 -
若
,那么我们把 和 进行缩点,原树转化为 个节点新树。将边 加入队列。
先使用队列输出边,再输出栈中的边
再给出这样的输出边的方案的正确性证明:
首先使用条件
此时有
其中仅可能包括根节点的
当
不妨设根节点的缩点点权为
此时根节点可以与任意一个相连的缩点合并,不妨设该点为
每次缩根节点和其相连的点就可以喽。
而我们根据栈输出的边正满足这样的条件,证明留给读者自行思考(doge)。
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define F first
#define S second
const int maxn=3e5+5;
int n,m,x;
ll a[maxn];
vector<pii>E[maxn];
bool vis[maxn];
queue<int>que;
stack<int>stk;
inline void dfs(int u)
{
vis[u]=true;
for(auto v:E[u])
{
if(vis[v.F]) continue;
dfs(v.F);
if(a[v.F]>=x) que.push(v.S),a[u]+=a[v.F]-x;
else stk.push(v.S);
}
}
int main()
{
ll sum=0;
scanf("%d%d%d",&n,&m,&x);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),sum+=a[i];
if(sum<1ll*(n-1)*x){printf("NO");return 0;}
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
E[u].push_back({v,i}),E[v].push_back({u,i});
}
dfs(1);
puts("YES");
while(!que.empty()) printf("%d\n",que.front()),que.pop();
while(!stk.empty()) printf("%d\n",stk.top()),stk.pop();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现