IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 6.19训练日记 -> 正文阅读

[数据结构与算法]6.19训练日记

P1129 [ZJOI2007] 矩阵游戏

链接
网格图是一个经典的二分图模型,在这题中.交换行列实际上就是交换节点的相对编号,但是对原本的边的连接情况仍然不变.
我们规定左部是行,右部是列.
比如说(1,3)上是1.对应着左部编号1连接右部编号3.
如果我们实行行变换,就是把这条对应的左部节点编号1情况换到另外一个节点的编号情况.比如交换行1与行2.
此时变为了(2,3)有1,对应编号2的点连接到右部编号3.
同理,如果交换列了,就是交换右部点的连接情况.
题目有解的情况是有n条这样的边.
(1,1),(2,2),(3,3).
既然我们从行列交换中发现,我们可以交换两个节点的相对编号来实现.行交换就是更改左部点的相对编号,列交换是更改右部的相对编号.
再仔细思考下,如果我们对于这个图含有一个完美匹配的时候,这个网格该是什么样的形状的.
就是存在一种方案,比如说n=3的时候
0 0 1
1 0 0
0 1 0
像这种,人为很容易地就能知道如何更改的情况.
把上面的图用二分图划出来,就会发现,只要通过行列交换,变换起始点与终点的编号,总是能构造出(1,1),(2,2)(3,3)这样的边.
所以,这个问题转化为求是否存在一个完美匹配.
跑网络流即可.

#include<bits/stdc++.h>
using namespace std;
const int maxn = 400+5;
const int INF = 1e9+7;
typedef long long ll;
typedef pair<int,int> pii;
struct Edge{
	int from,to,cap,flow;//起点,终点,容量,流量
};
struct Dicnic{
	int n,m,s,t;//点,边,源点,汇点
	vector<Edge> edges;//边集
	vector<int> G[maxn];
	bool vis[maxn];//bfs 使用的
	int d[maxn];//起点到i的距离,就是bfs得到的层次图,下次dfs沿着d走
	int cur[maxn];//当前弧优化使用
	void addEdge(int from,int to,int cap){
		edges.push_back({from,to,cap,0});
		edges.push_back({to,from,0,0});//反向边
		m = edges.size();
		G[from].push_back(m-2);G[to].push_back(m-1);
		//正边的编号都是偶数,反向边的编号都是奇数
	}
	bool bfs(){
		memset(vis,0,sizeof(vis));
		queue<int> Q;Q.push(s);
		d[s]=0;vis[s]=true;
		while(!Q.empty()){
			int x = Q.front();Q.pop();
			for(auto v : G[x]){
				Edge &e = edges[v];//获得边的编号
				if(!vis[e.to]&&e.cap>e.flow){
					//只有未被访问过,而且位于残量网络中的弧才考虑
					vis[e.to]=1;
					d[e.to]=d[x]+1;Q.push(e.to);
				}
			}
		}
		return vis[t];
	}
        int dfs(int x,int a){
		//寻找增广路,a代表目前经过的路中,每个边剩余的流量
		if(x==t||a==0) return a;//到达终点/残量为0
		int flow = 0,f;
		for(int &i = cur[x];i<G[x].size();i++){
			Edge &e = edges[G[x][i]];
			if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
				//首先要按层次图走,然后当前增加流量要是增广路中流量最小的的
				e.flow+=f;
				edges[G[x][i]^1].flow-=f;//正边加流量,反边减流量
				flow+=f;a-=f;
				if(a==0) break;
			}
		}
		return flow;
	}
	int Maxflow(int s,int t){
		this->s=s;this->t=t;
		int flow=0;
		while(bfs()){
			memset(cur,0,sizeof(cur));flow+=dfs(s,INF);
		}
		return flow;
	}
};
int main(){
    ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int T;cin>>T;
	while(T--){
		Dicnic g;
		int n;cin>>n;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				int ok;cin>>ok;
				if(ok){
					g.addEdge(i,n+j,1);
				}
			}
		}
		//源点
		int s = 0,t=2*n+2;
		for(int i=1;i<=n;i++) g.addEdge(s,i,1);
		for(int i=1;i<=n;i++) g.addEdge(n+i,t,1);
		int flow = g.Maxflow(s,t);
		if(flow==n) cout<<"Yes\n";
		else cout<<"No\n";
	}
}

B. Fake Plastic Trees

链接
给一个树带点权.初始点权为0,希望每个树的点权介于区间 [ l v , r v ] [l_v,r_v] [lv?,rv?]
定义一个操作:对于点 v v v到根1路径上所有节点,增加一个值 c v c_v cv?,但是要求从根到 v v v的值 c v c_v cv?是一个非递减的数字.
求最少操作数使得每个节点的点权都处于它们对应的区间上.
思考:对于一个叶子结点,因为其区间至少是大于1的,意味着每个叶子都至少占用一次操作数,
既然希望操作数最少,而且叶子加完后,下一次选择的路径也不会包含它们,所以一种可能最优的情况是叶子直接取 r v r_v rv?,对于它的父亲 u u u,可以选择的区间 [ 0 , m i n ( r u , r s o n ) ] [0,min(r_u,r_{son})] [0,min(ru?,rson?)],这暗示父亲在满足儿子节点的定义下,可以额外增加的值是可以计算出来的.
v a l u val_u valu? = m i n ( r u , ∑ r s o n ) min(r_u,\sum{r_{son}}) min(ru?,rson?)
继续思考,既然儿子的值已经被计算出来了,父亲这个点也已经不再需要额外考虑了,索性能加就加,加的值取 v a l u val_u valu?就行.
如果 v a l u > = l u val_u>=l_u valu?>=lu?,说明 u u u这个点已经不用继续考虑了,此时该点的取值就是 v a l u val_u valu?
,否则,这个点就成为一个新的"叶子",下一次新增加的值希望最大,取 r u r_u ru?

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e6+5;
const int INF = 1e9+7;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a) (a).begin(), (a).end()
vector<int> G[maxn];
int l[maxn],r[maxn];
int dp[maxn];//the number of op of the subtree(u)
int add[maxn];//the number of u.
void init(int n){
	for(int i=0;i<=n;i++) G[i].clear();
	for(int i=0;i<=n;i++) dp[i]=add[i]=0;
}
void dfs(int u,int fa){
	int child = 0;
	int val = 0;
	for(auto v : G[u]){
		if(v==fa) continue;
		dfs(v,u);child++;
		val += add[v];
		dp[u]+=dp[v]; 
	}
	if(child==0) dp[u]=1,add[u]=r[u];
	else{
		val = min(r[u],val);
		if(val<l[u]) dp[u]+=1,add[u] = r[u];
		else add[u]=val;
	}
}
signed main(){
    ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int T;cin>>T;
	while(T--){
		int n;cin>>n;
		init(n);
		for(int i=2;i<=n;i++){
			int p;cin>>p;
			G[i].push_back(p);
			G[p].push_back(i);
		}
		for(int i=1;i<=n;i++) cin>>l[i]>>r[i];
		dfs(1,0);
		cout<<dp[1]<<"\n";
	}
}

P1122 最大子树和

链接
求一个树的最大子树和.好像就是这样.dp乱搞一下先.

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
const int INF = 1e9+7;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a) (a).begin(), (a).end()
vector<ll> G[maxn];
ll val[maxn];ll dp[maxn];
void dfs(int u,int fa){
	dp[u] = val[u];
	for(auto v : G[u]){
		if(v==fa) continue;
		dfs(v,u);
		if(dp[v]>0) dp[u] += dp[v];
	}
}
int main(){
    ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	ll n;cin>>n;
	ll ans = 1LL*INF*100000*-1;
	for(int i=1;i<=n;i++) cin>>val[i],ans=max(val[i],ans);
	for(int i=1;i<=n-1;i++){
		int u,v;cin>>u>>v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs(1,0);
	ans = max(ans,dp[1]);
//	for(auto v : G[1]){
//		ans = max(ans,dp[v]);
//	}
	cout<<ans<<"\n";
return 0;}

摸了,今天状态不佳

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-06-26 17:03:41  更:2022-06-26 17:05:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:31:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码