2021CCPC桂林 E Buy and Delete
题目:
爱丽丝和鲍勃正在有向图 上玩游戏。在 中有 个顶点,标记为 。最初, 中没有边。爱丽丝会先从商店直接购买一些边,然后将它们添加到 中。之后,鲍勃需要删除边,直到 中没有边为止。在一轮删除中,鲍勃可以从 中删除一个边子集 ,这样当只保留 中的边时,图就是非循环的。请注意,爱丽丝可以什么也不买,在这种情况下,删除回合数为 。
商店中有 条边。爱丽丝有 美元,因此她要购买的边的总价不应超过 。爱丽丝希望最大化删除回合数,而鲍勃希望最小化删除回合数。爱丽丝和鲍勃都将以最优方式下棋。请编写一个程序来预测删除回合数。
输入
输入只包含一个案例。
输入的第一行包含三个整数 和 ( , , ),分别表示 中的顶点数、商店中的边数以及爱丽丝有多少美元。
在接下来的 行中, 行 包含三个整数 和 ( , ),表示商店中的一条有向边。爱丽丝可以支付 美元购买,并在 中添加一条从顶点 到顶点 的边。
输出
打印一行,其中包含一个整数,表示删除轮数。
分析:
无论几个环都会被删两轮,只有边没有环删一轮,还有一个边也买不起的情况为零轮。
求最小环即可时间复杂度为
代码:
vector<PII>e[N];
int n,m,c,minn,dist[N];
bool st[N];
void Dijkstra(int u){
minn=1e18;
for(int i=1;i<=n;i++)dist[i]=1e18,st[i]=0;
priority_queue<PII,vector<PII>,greater<PII> >q;
dist[u]=0;
q.push({dist[u],u});
while(q.size()){
auto [dis,ver]=q.top();
q.pop();
if(st[ver])continue;
st[ver]=1;
for(auto [v,w]:e[ver]){
if(v==u)minn=min(minn,dis+w);
if(st[v])continue;
if(dist[v]>dis+w){
dist[v]=dis+w;
q.push({dist[v],v});
}
}
}
}
void solve(){
cin>>n>>m>>c;
int ans=0;
for(int i=1;i<=m;i++){
int u,v,z;cin>>u>>v>>z;
e[u].pb({v,z});
if(z<=c)ans=1;
}
for(int i=1;i<=n;i++){
Dijkstra(i);
if(minn<=c){ans=2;break;}
}
}