8.26

又双叒叕把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
posted @ 2019-10-08 12:25  设计涉及社稷  阅读(129)  评论(0编辑  收藏  举报