又双叒叕把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
01-16 00:27