當前位置:
首頁 >
不止代码:路径数量(ybtoj-最小生成树)
發布時間:2023/12/3
40
豆豆
生活随笔
收集整理的這篇文章主要介紹了
不止代码:路径数量(ybtoj-最小生成树)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 題目描述
- 解析
- 代碼
題目描述
解析
乍一看:是個水題啊!
顯然如果途徑存在強連通的點,路徑就會變為正無窮
所以縮點加拓撲dp以及一些特判應該就可以解決了!
一交:40分。。。
然后就開始拆東墻補西墻的debug。。。
de到80之后實在無計可施,看了測試數據
最終在交了10余次后切掉了本題(淚目)
總結一下遇見的問題吧:
1.是所以超過36500的點視為相等,而不是有超過36500的點就全部認為相等!(gg:省選的虧還是沒吃夠啊。。。)
2.判斷強連通特判的位置應該在topu的while大循環的里面而不是判斷出邊的地方(如果這里不像人話可以看下面的代碼有注釋說明),否則入度為0的強連通會統計不上
3.有自環!!!!路徑也相當于正無窮!(就是這個地方卡80分一直沒想到,以后要培養題里沒說沒有就要考慮自環、重復路徑的思維)
4.在2的判斷的位置,不是所有有自環的或強連通都是可以的,至少。。它得能走到n+1點啊。。。
總的來說,本題是一道考驗嚴謹思維的題,數據出的很好,提升了本題的質量
我也要提升自己的質量!
代碼
#include<bits/stdc++.h> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int N=2e6+100; const int M=2e6+100; const int X=36500; int n,m; int cnt=-1,fi[N]; struct node{int to,nxt; }p[M]; void addline(int x,int y){p[++cnt]=(node){y,fi[x]};fi[x]=cnt; } int a,b; int zhan[N],dfs[N],low[N],col[N]; int ed,tot,tim; int size[N]; int self[N]; void tarjan(int x){zhan[++ed]=x;dfs[x]=low[x]=++tim;for(int i=fi[x];~i;i=p[i].nxt){int u=p[i].to;if(dfs[u]==0){tarjan(u);low[x]=min(low[x],low[u]);}else if(col[u]==0) low[x]=min(low[x],low[u]);}if(low[x]==dfs[x]){col[x]=++tot;size[tot]=1;if(self[x]) self[tot]=1;while(zhan[ed]!=x){if(self[zhan[ed]]) self[tot]=1;col[zhan[ed--]]=tot;size[tot]++;}ed--;} } int flag,dp[N],ru[N]; void topu(){queue<int>q;for(int i=n+1;i<=tot;i++) if(ru[i]==0) q.push(i);while(!q.empty()){int now=q.front();q.pop(); // printf("now=%d\n",now);if(self[now]&&dp[now]||dp[now]>X||(dp[now]&&size[now]!=1)){dp[now]=36501;}//剛才第二條說的就是上面的這個特判不能寫在下面的A處for(int i=fi[now];~i;i=p[i].nxt){int u=p[i].to;//A處就是這里啦 // printf("now=%d to=%d\n",now,u);dp[u]+=dp[now];if(--ru[u]==0){q.push(u);}}} } int ans,num,jd[N]; int main(){scanf("%d%d",&n,&m);n++;tot=n;mem(fi,-1);for(int i=1;i<=m;i++){scanf("%d%d",&a,&b);if(a==b) self[a]=1;else addline(b,a);//反向建圖 }for(int i=1;i<=n;i++){if(!dfs[i]) tarjan(i);}for(int i=1;i<=n;i++){int xx=col[i];for(int j=fi[i];~j;j=p[j].nxt){int yy=col[p[j].to];if(xx!=yy){addline(xx,yy);ru[yy]++;}}} // for(int i=1;i<=n+1;i++) printf("i=%d col=%d size=%d\n",i,col[i],size[col[i]]);dp[col[n]]=1;topu(); // for(int i=1;i<=n;i++) printf("i=%d dp=%d\n",i,dp[col[i]]); for(int i=n+1;i<=tot;i++){if(dp[i]>36500){flag=1,ans=36501;break;}else ans=max(ans,dp[i]);}for(int i=n+1;i<=tot;i++){if(dp[i]>=ans){num+=size[i];jd[i]=1;}}if(ans<=36500) printf("%d\n",ans);else printf("zawsze\n");printf("%d\n",num);for(int i=1;i<=n;i++){if(jd[col[i]]) printf("%d ",i);}return 0; } /* 3 2 3 4 4 3 */總結
以上是生活随笔為你收集整理的不止代码:路径数量(ybtoj-最小生成树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: qq公众号:服务号和订阅号、购物号有什么
- 下一篇: 理解至上:数位dp(ybtoj-B数计数