#define man 300050 int fa[man],opt,x,y,fx,fy,n,k,ans=0; int find(int x){ if(fa[x]==x) return fa[x]; return fa[x]=find(fa[x]); } int main(){ n=read();k=read(); for(rint i=1;i<=3*n;i++) fa[i]=i; //[1,n]同類;[n+1,2*n]獵物;[2*n+1,3*n]天敵; for(rint i=1;i<=k;i++){ opt=read();x=read();y=read(); if(x>n||y>n){ ans++;continue;} if(opt==1){ if(find(x+n)==find(y)||find(x+n+n)==find(y)){ ans++;continue;} //y是x的獵物或者天敵,謊話 fa[find(x)]=find(y);//x的同類是y的同類 fa[find(x+n)]=find(y+n);//x的獵物是y的獵物 fa[find(x+n+n)]=find(y+n+n);//x的天敵是y的天敵 } else if(opt==2){ if(find(x)==find(y)||find(x+n+n)==find(y)){ ans++;continue;} //x是y的同類或者y是x的天敵,謊話 fa[find(x)]=find(y+n+n);//y的天敵是x fa[find(x+n)]=find(y);//x的獵物是y fa[find(x+n+n)]=find(y+n);//x的天敵是y的獵物(由循環關係可得) } } cout<<ans<<endl; return 0; }
int n,m; int pos[2050];//第i個畫師的最後出現的下標 int pic[1000050];//畫做 int cnt,l=1;//已經出現的畫師的數量及不斷更新的左端點 int ml=0,mr=0,ans=1e9+7;//最終答案的左右端點及區間的長度 int main(){ n=read();m=read(); memset(pos,0,sizeof(pos)); for(rint i=1;i<=n;i++){ pic[i]=read(); if(!pos[pic[i]]) cnt++;//若是以前的畫師沒有出現過,那麼cnt+1 pos[pic[i]]=i;//將畫師的下標更新到最新的一幅 while(l!=i && l<pos[pic[l]]) l++;//若是最左邊的畫師的做品在後面的枚舉中出現過,那麼就能夠向後移動一個 if(cnt==m && i-l+1<ans)//若是數量足夠而且區間的長度更有,那麼更新 ml=l,mr=i,ans=i-l+1; } cout<<ml<<" "<<mr<<endl; return 0; }
3.差分約束spa
求最小值時用最長路,求最大值是用最短路code
P3275 [SCOI2011]糖果blog
#define man 1000050 int n,m; struct edge{ int next,to,dis;}e[man]; int head[man<<1],num=0; inline void add(int from,int to,int dis){ e[++num]=(edge){head[from],to,dis}; head[from]=num; } int dis[man],vis[man],cnt[man]; inline void spfa(int s){ queue<int>q; memset(dis,0,sizeof(dis)); memset(vis,0,sizeof(vis)); //memset(cnt,0,sizeof(cnt)); dis[s]=0;vis[s]=0;q.push(s); do{ int u=q.front();q.pop();vis[u]=0;cnt[u]++; if(cnt[u]>n){ printf("-1\n");exit(0);} for(rint i=head[u];i;i=e[i].next){ int to=e[i].to; if(dis[to]<dis[u]+e[i].dis){ dis[to]=dis[u]+e[i].dis; if(!vis[to]){ vis[to]=1; q.push(to); } } } }while(q.size()); } int main(){ //printf("%.3lf M\n",(double)sizeof(e)/(1<<20)); n=read();m=read(); for(rint i=1,opt,x,y;i<=m;i++){ opt=read();x=read();y=read(); if(opt==1) add(x,y,0),add(y,x,0); if(opt==2) add(x,y,1); if(opt==3) add(y,x,0); if(opt==4) add(y,x,1); if(opt==5) add(x,y,0); if(opt%2==0&&x==y){ printf("-1\n"); return 0; } } for(rint i=n;i>=1;i--) add(0,i,1); spfa(0); long long ans=0; for(rint i=1;i<=n;i++){ ans+=dis[i]; } printf("%lld\n",ans); return 0; }
4.二分圖匹配隊列
P2055 假期的宿舍get
#define man 55 int T,n; int a[man],b[man],c[man][man],tot,ans; int used[man],link[man]; bool find(int s){ for(rint i=1;i<=n;i++){ if(a[i]==1) if(c[s][i]==1&&used[i]==0){ used[i]=1; if(link[i]==0||find(link[i])){ link[i]=s; return 1; } } } return 0; } int main(){ T=read(); while(T--){ n=read(); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); memset(link,0,sizeof(link)); for(rint i=1;i<=n;i++) a[i]=read(); for(rint i=1;i<=n;i++) b[i]=read(); for(rint i=1,x;i<=n;i++) for(rint j=1;j<=n;j++){ x=read(); if(x==1||i==j) c[i][j]=1; } ans=0,tot=0; for(rint i=1;i<=n;i++){ memset(used,0,sizeof(used)); if(a[i]==0||(a[i]==1&&b[i]==0)){ tot++; if(find(i)) ans++; } } if(ans==tot) printf("^_^\n"); else printf("T_T\n"); } return 0; }