去年省选day2t1,清明来更新
------------------------------------------------------------------------------------- 这道题,边有很多,搜索肯定超时,求有多少组的问题,并查集是显然的,可是并查集由于有一个缩边的优化,导致删边成了最令人头疼的事,于是想到tarjan强连通分量的思想,把没有删边操作的点都通过并查集缩成一个点,然后搜索求答案,考虑到询问加边删边很少,以后的边加进来都作为图的边加进去,不参与缩点,搜索还有一个优化,求答案的时候不要每次重新求答案,而是根据上一次的来做相应的修改即可。。。。。。不得不吐槽数据太弱,一开始我缩完点后加边还是用原来的点的编号加的(father【i】打成i),居然还对了六个点。。。。。 3562: [SHOI2014]神奇化合物Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 233 Solved: 133 [ Submit][ Status][ Discuss] Description 科学家最近发现了一种高分子有机化合物 SHTSC。这种物质的分子由多个原子组成,原子之间通过化学键相互连接。SHTSC 十分不稳定,其原子之间的化学键经常会伴随着炫酷的声音特效和光影效果发生断裂或者重新连接。 Input 第一行两个整数:n, m。表示 SHTSC 的总原子个数以及初始的化学键数。 Output 对于每个 Q 操作,输出一行一个整数,为相应时刻的分子个数。 Sample Input
7 10
1 2 2 3 3 4 4 1 1 3 2 4 5 6 6 7 7 5 2 5 1 0 Q D 2 5 Q D 5 6 D 5 7 Q A 2 5 Q A 5 6 Q Sample Output
1
2 3 2 1 HINT
对于 100%的数据, n≤5000,m≤200000,q≤10000。 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<queue> #include<vector> #include<cstring> #include<cstdlib> #include<stack> using namespace std; const int maxn=5005; struct edge1{ int x,y; char c; }; struct edge{ int from,to; }; edge1 e1[500005],e2[10005]; vector<edge> edges; vector<int> g[maxn]; int n,p,m,f[maxn],ans=0,e3[maxn][maxn]={0}; bool d[maxn][maxn]={0},vis[maxn]={0};
inline int ReadInt() { char ch = getchar(); int data = 0; while (ch < '0' || ch > '9') { ch = getchar(); } do { data = data*10 + ch-'0'; ch = getchar(); }while (ch >= '0' && ch <= '9'); return data; }
int find(int x) { if (f[x]!=x) f[x]=find(f[x]); return f[x]; }
bool dfs(int s,int t) { if(s==t) return true; for (int i=0;i<g[s].size();i++) { edge e=edges[g[s][i]]; if (!vis[e.to]&&e3[s][e.to]>0) { vis[e.to]=1; if(dfs(e.to,t)) return true; } } return false;
}
bool bfs(int s,int t) //好像有错误,bfs不知道怎么回事有些数据比标答多1.。。。 { stack<int> q; q.push(s); vis[s]=1; while (!q.empty()) { int x=q.top(); q.pop(); for (int i=0;i<g[x].size();i++) { edge e=edges[g[x][i]]; if (!vis[e.to]&&e3[x][e.to]>0) { vis[e.to]=1; if (e.to==t) return true; q.push(e.to); } } } return false; }
void addedge(int x,int y) { memset(vis,0,sizeof(vis)); if (!dfs(x,y)) ans--; e3[x][y]++; e3[y][x]++; edge e; e.from=x; e.to=y; edges.push_back(e); e.from=y; e.to=x; edges.push_back(e); int m=edges.size(); g[x].push_back(m-2); g[y].push_back(m-1); return ; }
void del(int x,int y) { memset(vis,0,sizeof(vis)); e3[x][y]--; e3[y][x]--; if(!dfs(x,y)) ans++; return ; }
int main() { ans=0; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) f[i]=i; for (int i=1;i<=m;i++) { e1[i].x=ReadInt(); e1[i].y=ReadInt(); } scanf("%d",&p); for (int i=1;i<=p;i++) { scanf("%s",&e2[i].c); if (e2[i].c=='Q') continue; e2[i].x=ReadInt(); e2[i].y=ReadInt(); if (e2[i].c=='D') d[e2[i].y][e2[i].x]=d[e2[i].x][e2[i].y]=1; } for (int i=1;i<=m;i++) { int x=e1[i].x,y=e1[i].y; if (d[x][y]==1||d[y][x]==1) continue; x=find(x); y=find(y); if (x!=y) f[x]=y; }
for(int i=1;i<=n;i++) if((f[i]=find(i))==i) ans++; // for(int i=1;i<=n;i++) cout<<f[i]<< ' '; // cout<<endl; for (int i=1;i<=m;i++) { int x=e1[i].x,y=e1[i].y; if (f[x]!=f[y]) addedge(f[x],f[y]); }
for(int i=1;i<=p;i++) { int x=e2[i].x; int y=e2[i].y; if(e2[i].c=='Q') printf("%d\n",ans); else if(e2[i].c=='D') del(f[x],f[y]); else addedge(f[x],f[y]); } return 0; } |