又双叒叕把U盘忘在寝室了,所以把今下午的代码拷在这里
/* reference: translation: 有q次操作。每次会选定一个矩形区域。具体的每次给一组(x_1,y_1),(x_2,y_2)表示矩阵的左 下角和右上角。在这个矩阵所覆盖的每一个格子里,累加一个积木块。每个积木块可以可以抽 象为一个的正方体。现在,Venn想知道他们堆出来的物体的表面积。 solution: 【首先这并不是在线的询问,而是只询问一次,所以我们考虑对每个操作O(1)差分一下。】 1.n*m*q的暴力算法显然不可取,采用二维差分O(1)预处理,O(n^2)查询a[i][j]的高度。 2.如果这个位置有高度,ans+=2;(上表面和下表面),其他四个面看周围四个的心情 trigger: note: *二维差分 *表面积问题 record: 这道题开long long 会爆内存………………………………………… date: 2019.08.26 */ #define N 5001 int n,m,q; int cnt[N][N]; int main(){ rd(n);rd(m);rd(q); while(q--){ int x1,y1,x2,y2;rd(x1);rd(y1);rd(x2);rd(y2); cnt[x1][y1]++; cnt[x1][y2+1]--; cnt[x2+1][y1]--; cnt[x2+1][y2+1]++; } rep(i,1,n+1) rep(j,1,m+1) cnt[i][j]+=cnt[i-1][j]+cnt[i][j-1]-cnt[i-1][j-1]; long long ans=0; rep(i,1,n+1){ rep(j,1,m+1){ if(cnt[i][j])ans+=2; ans+=abs(cnt[i][j]-cnt[i-1][j])+abs(cnt[i][j]-cnt[i][j-1]); } } printf("%lld\n",ans); return 0; } /* 4 4 3 1 1 4 4 1 1 2 2 3 3 4 4 */ //64 /* 4 4 1 1 1 2 2 */ //16
dij
/* reference: translation: solution: trigger: note: * record: date: 2019.08.26 */ #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #define dwn(i,a,b) for(int i=a;i>=b;--i) template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} inline void write(int n){if(n==0)return;write(n/10);putchar(n%10+'0');} #define mem(a,b) memset(a,b,sizeof(a)) #define ee(i,u) for(int i=head[u];i;i=e[i].next) #define N 100010 int head[N],cnt,dis[N]; bool vis[N]; struct Edge{ int v,next,w; }e[N<<1]; void add(int u,int v,int w){e[++cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;} priority_queue<pair<int,int> > q; int n,m,s; inline void dij(){ mem(dis,0x3f); mem(vis,0); q.push(make_pair(0,1)); dis[1]=0; while(!q.empty()){ int u=q.top().second; q.pop(); if(vis[u])continue; vis[u]=1; ee(i,u){ int v=e[i].v,w=e[i].w; if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; q.push(make_pair(-dis[v],v)); } } } } int main(){ rd(n),rd(m); rep(i,1,m){ int x,y,z;rd(x),rd(y),rd(z); add(x,y,z); } dij(); printf("%d ",dis[n]==0x3f3f3f3f?-1:dis[n]); return 0; }
*问你是否存在负环的时候(没说S点),要把每一个点都作为起点spfa一遍
rep(i,1,n){ if(spfa(i)){ printf("Yes\n"); exit(0); } } printf("No\n");
最小费用最大流
/*给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。 第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。 接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。 一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。*/ /* reference: translation: solution: trigger: note: * record: date: 2019.08.26 */ #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #define dwn(i,a,b) for(int i=a;i>=b;--i) template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} inline void write(int n){if(n==0)return;write(n/10);putchar(n%10+'0');} #define mem(a,b) memset(a,b,sizeof(a)) #define ee(i,u) for(int i=head[u];i;i=e[i].next) #define N 100010 bool vis[N]; int n,m,s,t,x,y,z,f,cnt=1,maxflow,mincost; int head[N],dis[N],pre[N],last[N],flow[N]; struct edge{int v,next,flow,cost;}e[N]; queue<int>q; void add(int u,int v,int flow,int cost){ e[++cnt].v=v;e[cnt].flow=flow;e[cnt].cost=cost;e[cnt].next=head[u];head[u]=cnt; e[++cnt].v=u,e[cnt].flow=0;e[cnt].cost=-cost;e[cnt].next=head[v];head[v]=cnt; } bool spfa(int s,int t){ mem(dis,0x7f); mem(vis,0); mem(flow,0x7f); q.push(s); vis[s]=1; dis[s]=0; pre[t]=-1; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; ee(i,u){ int v=e[i].v,cost=e[i].cost; if(e[i].flow && dis[v]>dis[u]+cost){ dis[v]=dis[u]+cost; pre[v]=u; last[v]=i; flow[v]=min(flow[u],e[i].flow); if(!vis[v]){ vis[v]=1; q.push(v); } } } } return pre[t]!=-1; } int main(){ #ifdef WIN32 freopen("zxfyzdl.txt","r",stdin); #endif rd(n),rd(m),rd(s),rd(t); rep(i,1,m){ int u,v,cost,flow;rd(u),rd(v),rd(flow),rd(cost); add(u,v,flow,cost); } while(spfa(s,t)){ int u=t; maxflow+=flow[t]; mincost+=flow[t]*dis[t]; while(u!=s){ e[last[u]].flow-=flow[t]; e[last[u]^1].flow+=flow[t]; u=pre[u]; } } printf("%d %d",maxflow,mincost); return 0; } /* 4 5 4 3 4 2 30 2 4 3 20 3 2 3 20 1 2 1 30 9 1 3 40 5 */ //50 280
树的重心(WA)
/* reference: translation: solution: trigger: note: * record: date: 2019.08.26 */ #include<bits/stdc++.h> using namespace std; #define int long long #define rep(i,a,b) for(int i=a;i<=b;++i) #define dwn(i,a,b) for(int i=a;i>=b;--i) template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} inline void write(int n){if(n==0)return;write(n/10);putchar(n%10+'0');} #define mem(a,b) memset(a,b,sizeof(a)) #define ee(i,u) for(int i=head[u];i;i=e[i].next) #define N 10010 #define M struct edge{ int v,next; }e[N<<1]; int head[N],cnt,n,ans=INT_MAX,size[N]; inline void add(int u,int v){e[++cnt].v=v;e[cnt].next=head[u];head[u]=cnt;} int dfs(int u,int fa){ size[u]=1; int max_sub_tree=0; ee(i,u){ int v=e[i].v; if(v==fa)continue; int t=dfs(v,u); max_sub_tree=max(max_sub_tree,t); size[u]+=t; } max_sub_tree=max(max_sub_tree,n-size[u]); ans=min(ans,max_sub_tree); return size[u]+1; } #undef int int main(){ #define int long long #ifdef WIN32 freopen("zhongxin.txt","r",stdin); #endif rd(n); rep(i,1,n-1){ int u,v;rd(u),rd(v); add(u,v),add(v,u); } dfs(1,0); printf("%lld\n",ans); //rep(i,1,n)printf("%lld ",size[i]); return 0; } /* 9 1 2 1 7 1 4 2 8 2 5 4 3 3 9 4 6 */ //4
toposort
- 判断是否有TOPO排序:记录的序列已经到达n个了
/* reference: translation: solution: trigger: note: * record: 妈个鬼仙人啊,数组没开够,我还以为是哪里写错了 T^T date: 2019.08.26 */ #define N 100010 struct edge{ int v,next; }e[N]; int head[N],cnt,n,m,tot,deg[N],topon[N]; void add(int u,int v){e[++cnt].v=v;e[cnt].next=head[u];head[u]=cnt;} queue<int>q; bool topo(){ rep(i,1,n) if(!deg[i]) q.push(i); while(!q.empty()){ int u=q.front();q.pop(); topon[++tot]=u; ee(i,u){ int v=e[i].v; if(--deg[v]==0) q.push(v); } } return tot==n;////////////////////// } int main(){ #ifdef WIN32 freopen("","r",stdin); #endif rd(n),rd(m); rep(i,1,m){ int u,v;rd(u),rd(v); add(u,v);deg[v]++; } if(topo()){ rep(i,1,tot) printf("%d ",topon[i]); } else printf("-1\n"); return 0; } /* 3 3 1 2 2 3 1 3 */ //1 2 3
floyd
note: *如果有负权边,虽然a,b不连通,但之间的距离也会因为负权边的更新小于INF, 因为INF/2也是一个很大的数,所以就用>INF/2来代表不能连通 *一定要把dis[i][i]赋值为0! *可能会有重边 rep(i,1,n)dis[i][i]=0;///////////////////////////// dis[x][y]=min(dis[x][y],z);/////////////////////// if(dis[x][y]>0x3f3f3f3f/2)printf("impossible\n"); else printf("%d\n",dis[x][y]);
二分图最大匹配
/* reference: translation: solution: trigger: note: * record: date: 2019.08.26 */ #include<bits/stdc++.h> using namespace std; #define int long long #define rep(i,a,b) for(int i=a;i<=b;++i) #define dwn(i,a,b) for(int i=a;i>=b;--i) template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} #define mem(a,b) memset(a,b,sizeof(a)) #define ee(i,u) for(int i=head[u];i;i=m[i].next) #define N 1010 int n1,n2,m,g[N][N],match[N],vis[N]; inline bool dfs(int u){ rep(v,1,n2){ if(g[u][v]==1 && vis[v]==0){ vis[v]=1; if(match[v]==0 || dfs(match[v])){ match[v]=u; return 1; } } } return 0; } #undef int int main(){ #define int long long #ifdef WIN32 freopen("","r",stdin); #endif rd(n1),rd(n2),rd(m); while(m--){ int u,v;rd(u),rd(v); g[u][v]=1; } int ans=0;//为新郎找姑娘 mem(match,0);//初始化一下,目前新娘还没有被占领 rep(i,1,n1){//枚举新郎 mem(vis,0);//每次都重做一遍二分图匹配 if(dfs(i))ans++;//恭喜i号新郎找到林妹妹 } printf("%d",ans); return 0; } /* 2 2 4 1 1 1 2 2 1 2 2 */ //2
二分图染色
- col初始化为-1,通过~操作可得到-2和1
- 通过bfs来染色,注意要维护编号和一维值的关系时,可以make_pair
#define N 200010 int head[N],tot,col[N],s1,cnt,n,m; bool vis[N]; struct edge{ int v,w,next; }e[N<<1]; inline void add(int u,int v){e[++tot].v=v;e[tot].next=head[u];head[u]=tot;} queue<pair<int,int> >q; inline bool bfs(){ col[1]=1; q.push(make_pair(1,1)); while(!q.empty()){ int u=q.front().first; int color=q.front().second; q.pop(); ee(i,u){ int v=e[i].v; if(col[v]==-1){ col[v]=~color; q.push(make_pair(v,col[v])); } else if(col[v]==col[u])return 0; } } return 1; } int main(){ freopen("erfen.txt","r",stdin); rd(n),rd(m); rep(i,1,m){ int u,v;rd(u),rd(v); add(u,v),add(v,u); } mem(col,-1); if(bfs())printf("Yes\n"); else printf("No\n"); return 0; } /* 4 4 1 3 1 4 2 3 2 4 */ //Yes