2019 HL SC day1
今天讲的是图论大体上分为:有向图的强连通分量,有向图的完全图:竞赛图,无向图的的割点,割边,点双联通分量,变双联通分量以及圆方树 2-sat问题 支配树等等。
大体上都知道是些什么东西 但是仍需要写一些东西来好好巩固一下基础。太菜了 加油!。
1 有向图的强联通分量 写过好多次了 判断条件为dfn[x]==low[x] 此时栈中的所有点形成一个强连通分量。
bzoj 最受欢迎的牛:
- //#include<bits/stdc++.h>
- #include<iostream>
- #include<cmath>
- #include<ctime>
- #include<algorithm>
- #include<cctype>
- #include<utility>
- #include<queue>
- #include<map>
- #include<set>
- #include<bitset>
- #include<deque>
- #include<vector>
- #include<cstdio>
- #include<cstdlib>
- #include<iomanip>
- #include<stack>
- #include<string>
- #include<cstring>
- using namespace std;
- char buf[<<],*fs,*ft;
- inline char getc()
- {
- return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
- }
- inline int read()
- {
- int x=,f=;char ch=getc();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
- return x*f;
- }
- const int MAXN=;
- int n,m,len,cnt,top,num;
- struct wy
- {
- int x,y;
- }t[MAXN];
- int c[MAXN],b[MAXN],out[MAXN];
- int lin[MAXN],nex[MAXN],ver[MAXN];
- int s[MAXN],dfn[MAXN],low[MAXN],vis[MAXN];
- inline void add(int x,int y)
- {
- ver[++len]=y;
- nex[len]=lin[x];
- lin[x]=len;
- }
- inline void dfs(int x)
- {
- dfn[x]=low[x]=++cnt;
- s[++top]=x;vis[x]=;
- for(int i=lin[x];i;i=nex[i])
- {
- int tn=ver[i];
- if(!dfn[tn])
- {
- dfs(tn);
- low[x]=min(low[x],low[tn]);
- }
- else if(vis[tn])low[x]=min(low[x],dfn[tn]);
- }
- //cout<<x<<' '<<dfn[x]<<' '<<low[x]<<endl;
- if(dfn[x]==low[x])
- {
- int y;++num;
- //cout<<x<<endl;
- do
- {
- y=s[top--];
- c[y]=num;++b[num];
- vis[y]=;
- }
- while(y!=x);
- }
- }
- int main()
- {
- //freopen("1.in","r",stdin);
- n=read();m=read();
- for(int i=;i<=m;++i)
- {
- t[i].x=read();
- t[i].y=read();
- add(t[i].x,t[i].y);
- }
- for(int i=;i<=n;++i)if(!dfn[i])dfs(i);
- //cout<<num<<endl;
- for(int i=;i<=n;++i)
- for(int j=lin[i];j;j=nex[j])
- {
- int tn=ver[j];
- if(c[tn]==c[i])continue;
- ++out[c[i]];
- }
- int flag=;
- for(int i=;i<=num;++i)
- {
- if(out[i]==&&flag)
- {
- puts("");
- return ;
- }
- if(out[i]==&&flag==)flag=b[i];
- }
- printf("%d\n",flag);
- return ;
- }
杀人游戏:
- //#include<bits/stdc++.h>
- #include<iostream>
- #include<cmath>
- #include<ctime>
- #include<algorithm>
- #include<cctype>
- #include<utility>
- #include<queue>
- #include<map>
- #include<set>
- #include<bitset>
- #include<deque>
- #include<vector>
- #include<cstdio>
- #include<cstdlib>
- #include<iomanip>
- #include<stack>
- #include<string>
- #include<cstring>
- using namespace std;
- char buf[<<],*fs,*ft;
- inline char getc()
- {
- return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
- }
- inline int read()
- {
- int x=,f=;char ch=getc();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
- return x*f;
- }
- const int MAXN=;
- int n,m,len,cnt,top,num,sum,flag,len1;
- int lin[MAXN],ver[MAXN],nex[MAXN],out[MAXN];
- int lin1[MAXN],ver1[MAXN],nex1[MAXN];
- int vis[MAXN],s[MAXN];
- int dfn[MAXN],low[MAXN],b[MAXN],c[MAXN],in[MAXN];
- inline void add(int x,int y)
- {
- ver[++len]=y;
- nex[len]=lin[x];
- lin[x]=len;
- }
- inline void add1(int x,int y)
- {
- ver1[++len1]=y;
- nex1[len1]=lin1[x];
- lin1[x]=len1;
- }
- inline void dfs(int x)
- {
- dfn[x]=low[x]=++cnt;
- s[++top]=x;vis[x]=;
- for(int i=lin[x];i;i=nex[i])
- {
- int tn=ver[i];
- if(!dfn[tn])
- {
- dfs(tn);
- low[x]=min(low[x],low[tn]);
- }
- else if(vis[tn])low[x]=min(low[x],dfn[tn]);
- }
- if(dfn[x]==low[x])
- {
- ++num;int y;
- do
- {
- y=s[top];--top;
- c[y]=num;++b[num];
- vis[y]=;
- }
- while(x!=y);
- }
- }
- int main()
- {
- //freopen("1.in","r",stdin);
- n=read();m=read();
- for(int i=;i<=m;++i)
- {
- int x,y;
- x=read();y=read();
- add(x,y);
- }
- for(int i=;i<=n;++i)if(!dfn[i])dfs(i);
- //cout<<num<<endl;
- for(int i=;i<=n;++i)
- {
- for(int j=lin[i];j;j=nex[j])
- {
- int tn=ver[j];
- if(c[i]==c[tn])continue;
- //cout<<c[tn]<<' '<<i<<endl;
- add1(c[i],c[tn]);
- ++in[c[tn]];++out[c[i]];
- }
- }
- for(int i=;i<=num;++i)
- {
- if(!in[i])++sum;
- if(!in[i]&&!out[i]&&b[i]==)flag=;
- if(!in[i]&&b[i]==)
- {
- int mark=;
- for(int j=lin1[i];j;j=nex1[j])
- {
- int tn=ver1[j];
- if(in[tn]==)mark=;
- }
- if(!mark)flag=;
- }
- }
- printf("%.6lf\n",(n-sum+flag)*1.0/(n*1.0));
- return ;
- }
推荐一写 细节非常之多。
炸弹游戏 线段树优化建图+强连通分量。
线段树优化建图的话 我认为是 将一个点向一个区间整体连边 可转换成线段树上的连边 原因 我们不知道哪一条边起到了连接强连通分量的作用。
所以采用线段树优化一下边数至多为 2n+nlogn.
- //#include<bits/stdc++.h>
- #include<iostream>
- #include<cmath>
- #include<ctime>
- #include<algorithm>
- #include<cctype>
- #include<utility>
- #include<queue>
- #include<map>
- #include<set>
- #include<bitset>
- #include<deque>
- #include<vector>
- #include<cstdio>
- #include<cstdlib>
- #include<iomanip>
- #include<stack>
- #include<string>
- #include<cstring>
- #define INF 5000000000000000000ll
- #define l(x) t[x].l
- #define r(x) t[x].r
- #define mn(x) t[x].mn
- #define mx(x) t[x].mx
- #define ll long long
- #define mod 1000000007
- using namespace std;
- char buf[<<],*fs,*ft;
- inline char getc()
- {
- return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
- }
- inline ll read()
- {
- ll x=,f=;char ch=getc();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
- return x*f;
- }
- const int MAXN=;
- int n,cnt,top,root,num,len,len1,T,h,w;
- ll ans,vmn[MAXN<<],vmx[MAXN<<];
- int ru[MAXN<<],q[MAXN<<];
- int pos[MAXN],dfn[MAXN<<],low[MAXN<<],s[MAXN<<];
- int vis[MAXN<<],c[MAXN<<];
- int lin[MAXN<<],ver[MAXN*],nex[MAXN*];
- int lin1[MAXN<<],ver1[MAXN*],nex1[MAXN*];
- ll a[MAXN],b[MAXN];
- struct wy//动态开点线段树 优化建图
- {
- int l,r;
- ll mn,mx;
- }t[MAXN<<];
- inline void add(int x,int y)
- {
- ver[++len]=y;nex[len]=lin[x];lin[x]=len;
- }
- inline void add1(int x,int y)
- {
- ver1[++len1]=y;nex1[len1]=lin1[x];lin1[x]=len1;
- }
- inline void tarjan(int x)
- {
- dfn[x]=low[x]=++w;
- s[++top]=x;vis[x]=;
- for(int i=lin[x];i;i=nex[i])
- {
- int tn=ver[i];
- if(!dfn[tn])
- {
- tarjan(tn);
- low[x]=min(low[x],low[tn]);
- }
- else if(vis[tn])low[x]=min(low[x],dfn[tn]);
- }
- if(dfn[x]==low[x])
- {
- ++num;int y;
- vmn[num]=INF;vmx[num]=-INF;
- do
- {
- y=s[top--];
- vis[y]=;c[y]=num;
- vmn[num]=min(vmn[num],mn(y));
- vmx[num]=max(vmx[num],mx(y));
- }
- while(x!=y);
- }
- }
- inline void build(int &p,int l,int r)
- {
- if(!p)p=++cnt;
- if(l==r)
- {
- pos[l]=p;
- mn(p)=a[l];mx(p)=a[l];
- return;
- }
- int mid=(l+r)>>;
- build(l(p),l,mid);
- build(r(p),mid+,r);
- mn(p)=min(mn(l(p)),mn(r(p)));
- mx(p)=max(mx(l(p)),mx(r(p)));
- add(p,l(p));add(p,r(p));
- }
- inline void change(int p,int L,int R,int l,int r,int x)
- {
- if(L<=l&&R>=r)
- {
- add(x,p);
- return;
- }
- int mid=(l+r)>>;
- if(L<=mid)change(l(p),L,R,l,mid,x);
- if(R>mid)change(r(p),L,R,mid+,r,x);
- }
- inline void topsort()
- {
- while(h++<T)
- {
- int x=q[h];
- for(int i=lin1[x];i;i=nex1[i])
- {
- int tn=ver1[i];
- --ru[tn];
- vmn[tn]=min(vmn[tn],mn(x));
- vmx[tn]=max(vmx[tn],mx(x));
- if(!ru[tn])q[++T]=tn;
- }
- }
- }
- int main()
- {
- //freopen("1.in","r",stdin);
- n=read();
- for(int i=;i<=n;++i)a[i]=read(),b[i]=read();
- build(root,,n);
- for(int i=;i<=n;++i)
- {
- int l=lower_bound(a+,a++n,a[i]-b[i])-a;//这个一定不会越界
- int r=upper_bound(a+,a++n,a[i]+b[i])-a-;//这个有可能会越界但是不会出错
- //cout<<l<<' '<<r<<endl;
- //cout<<pos[i]<<endl;
- change(root,l,r,,n,pos[i]);
- }
- //cout<<cnt<<endl;
- for(int i=;i<=cnt;++i)if(!dfn[i])tarjan(i);
- //printf("%d\n",num);
- //cout<<(ll)num<<endl;
- for(int i=;i<=cnt;++i)
- {
- for(int j=lin[i];j;j=nex[j])
- {
- int tn=ver[j];
- if(c[i]==c[tn])continue;
- add1(c[tn],c[i]);++ru[c[i]];
- }
- }
- for(int i=;i<=num;++i)if(!ru[i])q[++T]=c[i];
- topsort();
- for(int i=;i<=n;++i)
- {
- int l=lower_bound(a+,a++n,vmn[c[pos[i]]])-a;
- int r=upper_bound(a+,a++n,vmx[c[pos[i]]])-a-;
- ans+=(ll)(r-l+)*(ll)i%mod;
- }
- printf("%lld\n",ans%mod);
- return ;
- }
割点:BLO 以前的代码。
- //#include<bits/stdc++.h>
- #include<iostream>
- #include<iomanip>
- #include<cmath>
- #include<cstdio>
- #include<ctime>
- #include<queue>
- #include<stack>
- #include<vector>
- #include<cctype>
- #include<utility>
- #include<algorithm>
- #include<cstring>
- #include<string>
- #include<map>
- #include<set>
- #include<bitset>
- #include<deque>
- #include<cstdlib>
- #define INF 2147483646
- #define ll long long
- #define db double
- using namespace std;
- char buf[<<],*fs,*ft;
- inline char getc()
- {
- return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
- }
- inline ll read()
- {
- ll x=,f=;char ch=getc();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
- return x*f;
- }
- inline void put(ll x)
- {
- x<?putchar('-'),x=-x:;
- ll num=;char ch[];
- while(x)ch[++num]=x%+'',x/=;
- num==?putchar(''):;
- while(num)putchar(ch[num--]);
- putchar('\n');return;
- }
- const ll MAXN=;
- ll n,m,num;
- ll ans[MAXN],dfn[MAXN],low[MAXN],cut[MAXN];
- ll sz[MAXN];//s[i]表示以i为根节点的子树大小
- ll lin[MAXN<<],nex[MAXN<<],ver[MAXN<<],len;
- inline void add(ll x,ll y)
- {
- ver[++len]=y;
- nex[len]=lin[x];
- lin[x]=len;
- }
- inline ll min(ll x,ll y){return x>y?y:x;}
- void tarjan(ll x)
- {
- dfn[x]=low[x]=++num;
- sz[x]=;ll flag=,sum=;
- for(ll i=lin[x];i;i=nex[i])
- {
- ll tn=ver[i];
- if(!dfn[tn])
- {
- tarjan(tn);
- sz[x]+=sz[tn];
- low[x]=min(low[x],low[tn]);
- if(low[tn]==dfn[x])
- {
- flag++;
- if(x!=||flag>)
- {
- cut[x]=;sum+=sz[tn];
- ans[x]+=sz[tn]*(n-sz[tn]-);
- }
- }
- }
- else low[x]=min(low[x],dfn[tn]);
- }
- if(cut[x])ans[x]+=(n-sum-)*sum;
- return;
- }
- int main()
- {
- //freopen("1.in","r",stdin);
- n=read();m=read();
- for(ll i=;i<=m;++i)
- {
- ll x,y;
- x=read();y=read();
- add(x,y);add(y,x);
- }
- tarjan();
- for(ll i=;i<=n;++i)put(ans[i]+(n-)*);
- return ;
- }
bzoj 3331 圆方树+树上差分 非常简单。
- //#include<bits/stdc++.h>
- #include<iostream>
- #include<cmath>
- #include<ctime>
- #include<algorithm>
- #include<cctype>
- #include<utility>
- #include<queue>
- #include<map>
- #include<set>
- #include<bitset>
- #include<deque>
- #include<vector>
- #include<cstdio>
- #include<cstdlib>
- #include<iomanip>
- #include<stack>
- #include<string>
- #include<cstring>
- #define INF 5000000000000000000ll
- #define l(x) t[x].l
- #define r(x) t[x].r
- #define mn(x) t[x].mn
- #define mx(x) t[x].mx
- #define ll long long
- #define mod 1000000007
- using namespace std;
- char buf[<<],*fs,*ft;
- inline char getc()
- {
- return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
- }
- inline ll read()
- {
- ll x=,f=;char ch=getc();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
- return x*f;
- }
- const int MAXN=,maxn=MAXN<<;
- int n,m,k,len,top,num,cnt,T;
- int dfn[MAXN],low[MAXN],s[MAXN];
- int lin[maxn],ver[maxn],nex[maxn];
- int f[MAXN<<][],d[MAXN<<],c[MAXN<<];
- vector<int>g[MAXN];
- inline void add(int x,int y)
- {
- ver[++len]=y;
- nex[len]=lin[x];
- lin[x]=len;
- }
- void tarjan(int x)
- {
- low[x]=dfn[x]=++cnt;
- s[++top]=x;
- for(unsigned int i=;i<g[x].size();++i)
- {
- int tn=g[x][i];
- if(!dfn[tn])
- {
- tarjan(tn);
- low[x]=min(low[x],low[tn]);
- if(dfn[x]==low[tn])
- {
- ++num;
- for(int j=;j!=tn;--top)
- {
- j=s[top];
- add(num,j);
- add(j,num);
- }
- add(num,x);
- add(x,num);
- }
- }
- else low[x]=min(low[x],dfn[tn]);
- }
- }
- inline void dfs(int x,int father)
- {
- d[x]=d[father]+;
- for(int i=lin[x];i;i=nex[i])
- {
- int tn=ver[i];
- if(tn==father)continue;
- f[tn][]=x;
- for(int j=;j<=T;++j)f[tn][j]=f[f[tn][j-]][j-];
- dfs(tn,x);
- }
- }
- inline int LCA(int x,int y)
- {
- if(d[x]<d[y])swap(x,y);
- for(int i=T;i>=;--i)
- if(d[f[x][i]]>=d[y])x=f[x][i];
- if(x==y)return x;
- for(int i=T;i>=;--i)
- if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
- return f[x][];
- }
- inline void dfs(int x)
- {
- for(int i=lin[x];i;i=nex[i])
- {
- int tn=ver[i];
- if(tn==f[x][])continue;
- dfs(tn);
- c[x]+=c[tn];
- }
- }
- int main()
- {
- //freopen("1.in","r",stdin);
- n=read();m=read();k=read();
- for(int i=;i<=m;++i)
- {
- int x,y;
- x=read();y=read();
- g[x].push_back(y);
- g[y].push_back(x);
- }
- num=n;tarjan();
- //cout<<num<<endl;
- T=(int)(log((n+num)*1.0)/log(2.0))+;
- dfs(,);
- //for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i),--top;
- for(int i=;i<=k;++i)
- {
- int x,y;
- x=read();y=read();
- int lca=LCA(x,y);
- ++c[x];++c[y];
- --c[lca];
- if(f[lca][])--c[f[lca][]];
- }
- dfs();
- for(int i=;i<=n;++i)printf("%d\n",c[i]);
- return ;
- }
luogu 4630 铁人两项
圆方树 + 特殊性质 +树形dp 想的还不是很成熟。
总之符合路径的一定是s 到 f 路径上的 圆点和方点 采用树形dp O(n)解决。
- //#include<bits/stdc++.h>
- #include<iostream>
- #include<cmath>
- #include<ctime>
- #include<algorithm>
- #include<cctype>
- #include<utility>
- #include<queue>
- #include<map>
- #include<set>
- #include<bitset>
- #include<deque>
- #include<vector>
- #include<cstdio>
- #include<cstdlib>
- #include<iomanip>
- #include<stack>
- #include<string>
- #include<cstring>
- #define INF 1000000000
- #define ll long long
- #define mod 1000000007
- using namespace std;
- char buf[<<],*fs,*ft;
- inline char getc()
- {
- return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
- }
- inline ll read()
- {
- ll x=,f=;char ch=getc();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
- return x*f;
- }
- const int MAXN=,maxn=MAXN<<;
- int n,m,k,len,top,num,cnt,sz;
- ll ans;
- int dfn[MAXN],low[MAXN],s[MAXN],w[MAXN<<];
- int lin[maxn],ver[maxn],nex[maxn],b[MAXN<<];
- vector<int>g[MAXN];
- inline void add(int x,int y)
- {
- ver[++len]=y;
- nex[len]=lin[x];
- lin[x]=len;
- }
- void tarjan(int x)
- {
- low[x]=dfn[x]=++cnt;
- s[++top]=x;++sz;
- for(unsigned int i=;i<g[x].size();++i)
- {
- int tn=g[x][i];
- if(!dfn[tn])
- {
- tarjan(tn);
- low[x]=min(low[x],low[tn]);
- if(dfn[x]==low[tn])
- {
- ++num;
- for(int j=;j!=tn;--top)
- {
- j=s[top];
- add(num,j);
- add(j,num);
- ++w[num];
- }
- add(num,x);
- add(x,num);
- ++w[num];
- }
- }
- else low[x]=min(low[x],dfn[tn]);
- }
- }
- inline void dfs(int x,int father)
- {
- b[x]=x<=n;
- for(int i=lin[x];i;i=nex[i])
- {
- int tn=ver[i];
- if(tn==father)continue;
- dfs(tn,x);
- ans+=2ll*w[x]*b[x]*b[tn];
- b[x]+=b[tn];
- }
- ans+=2ll*w[x]*b[x]*(sz-b[x]);
- return;
- }
- int main()
- {
- //freopen("1.in","r",stdin);
- n=read();m=read();
- for(int i=;i<=n;++i)w[i]=-;
- for(int i=;i<=m;++i)
- {
- int x,y;
- x=read();y=read();
- g[x].push_back(y);
- g[y].push_back(x);
- }
- num=n;
- for(int i=;i<=n;++i)
- if(!dfn[i])
- {
- sz=;
- tarjan(i);--top;
- dfs(i,);
- }
- printf("%lld\n",ans);
- return ;
- }
luogu 3225 矿场搭建
点双连通分量 其实也是割点的裸题 很有意思。
- //#include<bits/stdc++.h>
- #include<iostream>
- #include<cstdio>
- #include<iomanip>
- #include<cstring>
- #include<string>
- #include<cstdlib>
- #include<cmath>
- #include<algorithm>
- #include<cctype>
- #include<utility>
- #include<set>
- #include<bitset>
- #include<queue>
- #include<stack>
- #include<deque>
- #include<map>
- #include<vector>
- #include<ctime>
- #define INF 2147483646
- #define ll long long
- using namespace std;
- char buf[<<],*fs,*ft;
- inline char getc()
- {
- return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
- }
- inline int read()
- {
- int x=,f=;char ch=getc();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
- return x*f;
- }
- inline void put(int x)
- {
- x<?putchar('-'),x=-x:;
- int num=;char ch[];
- while(x)ch[++num]=x%+'',x/=;
- num==?putchar(''):;
- while(num)putchar(ch[num--]);
- putchar('\n');return;
- }
- const int MAXN=;
- int n,len,num,root,c,cnt,sum,m,w;
- ll ans;
- int low[MAXN],dfn[MAXN],cut[MAXN],vis[MAXN];
- int lin[MAXN<<],nex[MAXN<<],ver[MAXN<<];
- inline void add(int x,int y)
- {
- ver[++len]=y;
- nex[len]=lin[x];
- lin[x]=len;
- }
- inline int max(int x,int y){return x>y?x:y;}
- inline int min(int x,int y){return x>y?y:x;}
- void tarjan(int x)
- {
- dfn[x]=low[x]=++num;
- int flag=;
- for(int i=lin[x];i;i=nex[i])
- {
- int tn=ver[i];
- if(dfn[tn]){low[x]=min(low[x],dfn[tn]);continue;}
- else
- {
- tarjan(tn);
- low[x]=min(low[x],low[tn]);
- if(dfn[x]==low[tn])
- {
- ++flag;
- if(flag>||x!=root)cut[x]=;
- }
- }
- }
- }
- void dfs(int x)
- {
- vis[x]=cnt;++sum;
- for(int i=lin[x];i;i=nex[i])
- {
- int tn=ver[i];
- if(cut[tn]&&vis[tn]!=cnt)
- {
- vis[tn]=cnt;
- ++c;
- }
- if(!vis[tn]&&!cut[tn])dfs(tn);
- }
- }
- int main()
- {
- //freopen("1.in","r",stdin);
- for(int T=;;++T)
- {
- n=read();
- if(!n)break;
- memset(cut,,sizeof(cut));
- memset(dfn,,sizeof(dfn));
- memset(low,,sizeof(low));
- memset(lin,,sizeof(lin));
- memset(vis,,sizeof(vis));
- len=;num=;cnt=;ans=;m=;w=;
- for(int i=;i<=n;++i)
- {
- int x,y;
- x=read();y=read();
- m=max(m,max(x,y));
- add(x,y);add(y,x);
- }
- for(int i=;i<=m;++i)if(!dfn[i])root=i,tarjan(i);
- for(int i=;i<=m;++i)
- {
- if(vis[i]||cut[i])continue;
- ++cnt;sum=;c=;
- dfs(i);
- if(!c)ans=ans*(sum-)*sum/,w+=;
- if(c==)ans*=sum,w+=;
- if(c==);
- }
- printf("Case %d: %d %lld\n",T,w,ans);
- }
- return ;
- }
bzoj 3495 2-sat模型 需要前缀和优化建图 很有意思。
- //#include<bits/stdc++.h>
- #include<iostream>
- #include<cmath>
- #include<ctime>
- #include<algorithm>
- #include<cctype>
- #include<utility>
- #include<queue>
- #include<map>
- #include<set>
- #include<bitset>
- #include<deque>
- #include<vector>
- #include<cstdio>
- #include<cstdlib>
- #include<iomanip>
- #include<stack>
- #include<string>
- #include<cstring>
- #define INF 1000000000
- #define ll long long
- #define mod 1000000007
- using namespace std;
- char buf[<<],*fs,*ft;
- inline char getc()
- {
- return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
- }
- inline int read()
- {
- int x=,f=;char ch=getc();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
- return x*f;
- }
- const int MAXN=,maxn=MAXN<<;
- int n,m,k,len,cnt,top,num,flag;
- int c[MAXN<<];
- int lin[maxn],ver[maxn],nex[maxn];
- int s[MAXN<<],dfn[MAXN<<],low[MAXN<<],vis[MAXN<<];
- inline void add(int x,int y)
- {
- ver[++len]=y;
- nex[len]=lin[x];
- lin[x]=len;
- }
- inline void tarjan(int x)
- {
- dfn[x]=low[x]=++cnt;
- s[++top]=x;vis[x]=;
- for(int i=lin[x];i;i=nex[i])
- {
- int tn=ver[i];
- if(!dfn[tn])
- {
- tarjan(tn);
- low[x]=min(low[x],low[tn]);
- }
- else if(vis[tn])low[x]=min(low[x],dfn[tn]);
- }
- if(dfn[x]==low[x])
- {
- ++num;int y;
- do
- {
- y=s[top--];
- vis[y]=;c[y]=num;
- }
- while(x!=y);
- }
- }
- int main()
- {
- //freopen("1.in","r",stdin);
- n=read();m=read();k=read();
- for(int i=;i<=m;++i)
- {
- int x,y;
- x=read();y=read();//x选 x+n不选
- add(x+n,y);add(y+n,x);
- }
- for(int i=;i<=k;++i)
- {
- int w;
- w=read();
- for(int j=;j<=w;++j)s[j]=read();
- for(int j=;j<=w;++j)add(s[j]+*n,s[j-]+*n);//前缀和
- for(int j=w-;j>=;--j)add(s[j]+*n,s[j+]+*n);//后缀和
- for(int j=;j<=w;++j)
- {
- if(j>)add(s[j],s[j-]+*n);
- if(j<w)add(s[j],s[j+]+*n);
- }
- }
- for(int i=;i<=n;++i)add(i+*n,i+n),add(i+*n,i+n);
- for(int i=;i<=*n;++i)if(!dfn[i])tarjan(i);
- for(int i=;i<=n;++i)if(c[i]==c[i+n])flag=;
- if(flag)puts("NIE");else puts("TAK");
- return ;
- }
2019 HL SC day1的更多相关文章
- 2019 HL SC day10
10天都过去了 4天都在全程懵逼.. 怎么可以这么难啊 我服了 现在想起依稀只记得一些结论 什么 反演? 什么后缀自动机?什么组合数的应用?什么神仙东西 ,不过讲课人的确都是神仙.(实名羡慕. mzx ...
- 2019 HL SC day4
自闭场本来 以为 顶多一些不太会 结果发现 一堆不太会 . 树状数组 感觉 好久没看 了有点遗忘 不过还好 现在我来了.莅临之神将会消灭一切知识点哦. 今天说点不一样东西 树状数组 hh 很有用的东 ...
- 2019 HL SC day2
今天讲的是网络流 大部分题目都写过了 这里 就总结一番. bzoj 1066 裸的最大流 不过需要拆点细节方面有一点坑 剩下的 没什么了. //#include<bits/stdc++.h> ...
- Solr分组查询
项目中需要实时的返回一下统计的东西,因此就要进行分组,在获取一些东西,代码拿不出来,因此分享一篇,还是很使用的. facet搜索 /** * * 搜索功能优化-关键词搜索 * 搜索范围:商品名称.店 ...
- Light of future-冲刺集合
table th:nth-of-type(1) { width: 85px; } table th:nth-of-type(2){ width: 80px; } table th:nth-of-typ ...
- Light of future-冲刺总结
目录 1.凡事预则立.测试博客的链接 2.包含冲刺日志集合随笔的所有内容 3.描述项目预期计划 7.代码仓库地址.测试文档链接地址.PPT链接地址 归属班级 →2019秋福大软件工程实践Z班 作业要求 ...
- Python3的日期和时间
2019独角兽企业重金招聘Python工程师标准>>> python 中处理日期时间数据通常使用datetime和time库 因为这两个库中的一些功能有些重复,所以,首先我们来比较一 ...
- 【LOJ】#3032. 「JOISC 2019 Day1」馕
LOJ#3032. 「JOISC 2019 Day1」馕 处理出每个人把馕切成N段,每一段快乐度相同,我们选择第一个排在最前的人分给他的第一段,然后再在未选取的的人中选一个第二个排在最前的切一下,并把 ...
- 【LOJ】#3031. 「JOISC 2019 Day1」聚会
LOJ#3031. 「JOISC 2019 Day1」聚会 听说随机可过? 我想了很久想了一个不会被卡的做法,建出前\(u - 1\)个点的虚树,然后找第\(u\)个点的插入位置,就是每次找一条最长链 ...
随机推荐
- 我终于弄懂了Python的装饰器(一)
此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 一 ...
- day36 作业
客户端 import struct import json from socket import * client=socket(AF_INET,SOCK_STREAM) # client.conne ...
- Python 字符串改变
在Python中,字符串是不可变类型,即无法直接修改字符串的某一位字符. 因此改变一个字符串的元素需要新建一个新的字符串. 常见的修改方法有以下4种. 方法1:将字符串转换成列表后修改值,然后用joi ...
- 李航统计学习方法(第二版)(五):k 近邻算法简介
1 简介 k近邻法的输入为实例的特征向量,对应于特征空间的点;输出为实例的类别,可以取多类.k近邻法假设给定一个训练数据集,其中的实例类别已定.分类时,对新的实例,根据其k个最近邻的训练实例的类别,通 ...
- bzoj3437小P的牧场
bzoj3437小P的牧场 题意: n个牧场,在每个牧场见控制站的花费为ai,在该处建控制站能控制从此处到左边第一个控制站(或边界)之间的牧场.一个牧场被控制的花费等于它到控制它的控制站之间的牧场数目 ...
- bilibili自定义调整视频播放速度
自定义调整视频播放速度 在b站的播放页面,按下f12,打开控制台 在控制台中复制下面代码,想几倍速就把2.5改成你想要的播放速度 document.querySelector('video').pla ...
- C/C++中的 if(指针变量) 和 if(!指针变量)
目录 if(指针变量) 代码演示 if(指针变量) 解读代码 if(!指针变量) 解读代码 总结 替代方案.推荐写法!!!!! if(指针变量) 当把一个指针作为条件表达式时,所要判断的条件实际上就是 ...
- ClickHouse源码笔记2:聚合流程的实现
上篇笔记讲到了聚合函数的实现并且带大家看了聚合函数是如何注册到ClickHouse之中的并被调用使用的.这篇笔记,笔者会续上上篇的内容,将剖析一把ClickHouse聚合流程的整体实现. 第二篇文章, ...
- 爆力破解Windows操作系统登录密码核心技术
一.不借助U盘等工具二.已将win7登录账户为test,密码为666666,全套C/C++黑客资料请加:726920220QQ 1.将电脑开机关机几次,进入以下界面
- docker环境部署mysql
参考文档 docker官方:https://hub.docker.com/_/mysql/?tab=description 部署步骤 1. 拉取镜像 这里我拉取了tag为5.7的镜像 docker p ...