原题
写一个非常符合直觉的做法,这题肯定要强联通分量缩点,缩完点之后呢?我们发现逆向边只有一条,这启示我们可以通过分层图的方法来解决这个题目。同层连正边,异层连反边即可,边权是每个联通分量的大小。跑一遍 dij
即可。时间复杂度应该是 O(nlogm) 的,代码实现很简单。
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int N=1e5+5;
int n,vis[N],dfn[N],low[N],st[N],top,sc,id[N],cnt,mark[N],siz[N],f[N],res[N],m;
int dis[N][2],ans;
vector<int>e[N],g[N];
struct node {
int v,w,fl;
bool operator <(const node &a)const {
return w>a.w;
}
};
vector<node>h[N][2];
pii b[N];
void tarjan(int u) {
vis[u]=1;
dfn[u]=low[u]=++cnt;
st[++top]=u,mark[u]=1;
for(int p:e[u]) {
if(!dfn[p])tarjan(p),low[u]=min(low[u],low[p]);
else if(mark[p])low[u]=min(low[u],dfn[p]);
}
if(dfn[u]==low[u]) {
++sc;
int y;
do {
y=st[top--],siz[sc]++;
id[y]=sc,mark[y]=0;
g[sc].push_back(y);
} while(u!=y);
}
}
signed main() {
scanf("%d%d",&n,&m);
for(int i=1,x,y; i<=m; i++) {
scanf("%d%d",&x,&y);
e[x].push_back(y);
b[i]= {x,y};
}
for(int i=1; i<=n; i++)
if(!vis[i])tarjan(i);
for(int i=1; i<=m; i++) {
if(id[b[i].first]==id[b[i].second ])continue;
h[id[b[i].first]][0].push_back({id[b[i].second],siz[id[b[i].second]],0});
h[id[b[i].first]][1].push_back({id[b[i].second],siz[id[b[i].second]],1});
h[id[b[i].second]][0].push_back({id[b[i].first],siz[id[b[i].first]],1});
}
memset(dis,-0x3f,sizeof dis);
dis[id[1]][0]=0;
priority_queue<node>q;
q.push({id[1],dis[id[1]][0],0});
while(!q.empty()) {
int x=q.top().v,d=q.top().w,fl=q.top().fl;
q.pop();
if(d!=dis[x][fl])continue;
for(auto tmp:h[x][fl]) {
int v=tmp.v ,w=tmp.w,fl1=tmp.fl;
if(dis[v][fl1]<dis[x][fl]+w) {
dis[v][fl1]=dis[x][fl]+w;
q.push({v,dis[v][fl1],fl1});
if(v==id[1]) {
ans=max(ans,dis[v][fl1]);
}
}
}
}
cout<<ans<<endl;
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】