Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 1398 Accepted Submission(s): 320
感想:
当时被爆栈爆到无语了。完全不知道为什么的爆栈。 这个题目讲的很清楚。。方法也很容易看出来,就是求无向图的桥的问题。问题是!他竟然无缘无故爆栈!! 心情都爆没了。超想骂数据。。后来看到标程时。。
这三条语句不知道干什么的:
int size = 256 << 20; // 256MB/ char *p = (char*)malloc(size) + size; __asm__("movl %0, %%esp\n" :: "r"(p) );
百度后发现跟什么寄存器有关系。。。可是这跟我爆栈有关系么??
当我把这几句删掉后,标程都是爆栈。。 然后我就彻底无语了。。。真的无语了。。真的真的很无语。。 我实在很佩服当时那些能AC的大牛们。。真不知道你们怎么解决爆栈的问题的。。
/* * @author ipqhjjybj * @date 20130727 * */ #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <iostream> #include <cmath> #include <algorithm> #include <cstring> #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) const int N=222222,M=2222222; int dfn[N],low[N],sig,ret,firstEdge[N],nextEdge[M],to[M],cnt,vst[M],dp[N][2]; int n,m; void addEdge(int u,int v){ to[cnt]=v; nextEdge[cnt]=firstEdge[u]; firstEdge[u]=cnt++; } void tarjan(int u){ dp[u][0]=dp[u][1]=0; dfn[u]=low[u]=sig++; for(int st=firstEdge[u];st!=-1;st=nextEdge[st]){ if(!vst[st>>1]){ vst[st>>1]=1; int v=to[st]; if(dfn[v]==-1){ tarjan(v); low[u]=min(low[u],low[v]); ret+=dfn[u]<low[v]; int temp=dp[v][0]+(dfn[u]<low[v]); if(temp>dp[u][0]){ dp[u][1]=dp[u][0]; dp[u][0]=temp; }else if(temp>dp[u][1]) dp[u][1]=temp; }else{ low[u]=min(low[u],dfn[v]); } } } } int main(){ //freopen("1002.in","r",stdin); int size = 256 << 20; // 256MB/ char *p = (char*)malloc(size) + size; __asm__("movl %0, %%esp\n" :: "r"(p) ); while(scanf("%d %d",&n,&m) && n+m){ cnt=0;memset(firstEdge,-1,sizeof(firstEdge)); for(int i=0,a,b;i<m;i++){ scanf("%d %d",&a,&b); addEdge(a-1,b-1); addEdge(b-1,a-1); } memset(dfn,-1,sizeof(dfn)); memset(vst,0,sizeof(vst)); sig=0,ret=0; tarjan(0); int ans=0; for(int i=0;i<n;i++) ans=max(ans,dp[i][0]+dp[i][1]); printf("%d\n",ret-ans); } return 0; }
本来想接着用说的思路写的,就是双连通+缩点+树最长直径来做。后来看到标程这个DP用的真的很好哇。。。省了好多代码。 其实这就是找一条直径方法比较快的浓缩了。
标准程序还是挺好的,就是爆栈的数据让我无语了。。
恩。。接着决定继续好好学习