公司云网站建设,国内顶尖设计椅子图片,保险网站导航,推广普通话奋进新征程ppt题意 给出一张DAG,要求删除尽量多的边使得连通性不变.(即:若删边前u到v有路径,则删边后仍有路径).点数30000,边数100000. 分析 如果从u到v有(u,v)这条边,且从u到v只有这一条路径,那么这条边必须保留.否则这条边一定可以删除.因为如果有不止一条路径从u到v,必然存在点x(x!u,x!v)…题意 给出一张DAG,要求删除尽量多的边使得连通性不变.(即:若删边前u到v有路径,则删边后仍有路径).点数30000,边数100000. 分析 如果从u到v有(u,v)这条边,且从u到v只有这一条路径,那么这条边必须保留.否则这条边一定可以删除.因为如果有不止一条路径从u到v,必然存在点x(x!u,x!v)使得u可到达x,x可到达v.而删边后必然也满足u可到达x,x可到达v,所以直接删掉(u,v)这条边就可以了. 刚才的分析已经给出了一个判定方法.既然如果有不止一条路径从u到v,必然存在点x(x!u,x!v)使得u可到达x,x可到达v,那么我们对每条边(u,v),枚举是否存在这样的x即可.这需要我们求出每个点能到达的点的集合,以及能到达这个点的集合.大力压位一波就好了.因为是DAG所以这个集合可以递推.复杂度O(nm/32).其实这题是看内存猜算法系列,榜上清一色的120多兆,不是压位还能是啥我是200多兆 #includecstdio
const int mod1000000007;
const int maxn30005,maxm200005;
struct edge{int to,next;
}lst[maxm],lst2[maxm];int len1,first[maxn],len21,first2[maxn];
void addedge(int a,int b){lst[len].tob;lst[len].nextfirst[a];first[a]len;
}
void addedge2(int a,int b){lst2[len2].tob;lst2[len2].nextfirst2[a];first2[a]len2;
}
int sz;
int reach[maxn][maxn/322],from[maxn][maxn/322];
int getbit(int u,int x){return (reach[u][x/32](x31))1;
}
void revbit(int u,int x){reach[u][x/32]^(1(x31));
}
void revbit2(int u,int x){from[u][x/32]^(1(x31));
}
bool vis[maxn];
void dfs(int x){if(vis[x])return;vis[x]true;for(int ptfirst[x];pt;ptlst[pt].next){dfs(lst[pt].to);for(int i0;isz;i)reach[x][i]|reach[lst[pt].to][i];}revbit(x,x);
}
void dfs2(int x){if(vis[x])return;vis[x]true;for(int ptfirst2[x];pt;ptlst2[pt].next){dfs2(lst2[pt].to);for(int i0;isz;i)from[x][i]|from[lst2[pt].to][i];}revbit2(x,x);
}
int main(){int n,m;scanf(%d%d,n,m);sz(n31)/321;for(int i1,a,b;im;i){scanf(%d%d,a,b);addedge(a,b);addedge2(b,a);}for(int i1;in;i)if(!vis[i])dfs(i);for(int i1;in;i)vis[i]0;for(int i1;in;i)if(!vis[i])dfs2(i);for(int i1;in;i)revbit(i,i),revbit2(i,i);int ans0;for(int i1;in;i){for(int ptfirst[i];pt;ptlst[pt].next){int ylst[pt].to;for(int j0;jsz;j){if(from[y][j]reach[i][j]){ans;break;}}}}printf(%d\n,ans);return 0;
}转载于:https://www.cnblogs.com/liu-runda/p/6921499.html