2018 Spring Training 图论 合集

YOLOv8【第十六章:可视化、论文复现与写作篇·第15节】Introduction 写作逻辑:如何讲好“Motivation”故事! 🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏。该专栏系统复现并梳理全网各类 YOLOv8 改进与实战案例(当前已覆盖分类 / 检测 / 分割 / 追踪 / 关键点 / OBB 检测等方向),坚持持续更新 + 深度解析,质量分长期稳定在 97 分以上,可视为当前市面上 覆盖较全、更新较快、实战导向极强 的 YOLO 改进系列内容之一。 阅读详情

https://cn.vjudge.net/contest/229893#overview 题目链接
A.Uva 302
判断能不能走就是一个一笔画问题,(欧拉回路),因为题目要求是要回到原点,因此所有点的度都必须是偶数才能满足要求。操蛋的是输出路径的时候是要输出路径 编号并且要求输出路径编号字典序最小的路径。本蒟蒻没想到什么好办法,于是每个点拿了一个map存路径,第一个键值是路径的编号,第二个则是路径的另一个端点。
代码写的非常丑陋QAQ
PS:这题在uva和poj上的格式要求不一样,疯狂pe –

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
int e[50][50];vector<int>road;int n;map<int,int>mp[50];bool used[2000];
void euler(int u)
{
    map<int,int>::iterator iter;
    for(iter=mp[u].begin();iter!=mp[u].end();iter++){
        if(!used[iter->first]&&e[u][iter->second]){
            e[u][iter->second]--;e[iter->second][u]--;used[iter->first]=true;
            euler(iter->second);road.push_back(iter->first);//mp[u].erase(iter);
        }
    }
}
int main()
{
    int x,y,z;
    step:while(cin>>x>>y&&x&&y){
        cin>>z;int degree[50]={0};road.clear();memset(used,0,sizeof(used));
        for(int i=1;i<=n;i++)mp[i].clear();
        memset(e,0,sizeof(e));e[x][y]++;e[y][x]++;
        mp[x][z]=y;mp[y][z]=x;
        degree[x]++;degree[y]++;int begin=min(x,y);n=0;
        while(cin>>x>>y&&x&&y){
            cin>>z;
            e[x][y]++;e[y][x]++;
            mp[x][z]=y;mp[y][z]=x;
            degree[x]++;degree[y]++;n=max(n,max(x,y));
        }
        for(int i=1;i<=n;i++)
            if(degree[i]%2){
            puts("Round trip does not exist.");goto step;
        }
        euler(begin);//road.push_back(begin);
        while(road.size()>1){
            cout<<road.back()<<' ';road.pop_back();
        }
        cout<<road.back()<<endl;
        //cout<<endl;
    }

    return 0;
}

B. POJ 1062
题意不太好懂,反正看懂之后就是一个最短路问题,但是有个问题就是等级限制,那么我们就枚举等级限制就好了,从区间[酋长等级-limit,酋长等级]一直枚举到[酋长等级,酋长等级+k],(题目似乎没有保证酋长等级一定最高?),每次枚举时】那些主人等级不在区间内的物品就被标记为inque,然后跑一发spfa,最后比较所有的最小值即可。(不过当时好像写了dijkstra23333)

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cstring>
using namespace std;
typedef struct {
    int to, cost;
}Edge;
vector<Edge>G[105];
typedef pair<int, int>P;
priority_queue<P, vector<P>, greater<P> >q;
int book[105], dis[105];
int dijkstra(void)
{
    int i,j;
    while (!q.empty()) {
        P p = q.top(); q.pop();
        if (book[p.second] == 1) continue;
        book[p.second] = 1;
        for (i = 0; i < G[p.second].size(); i++) {
            Edge temp = G[p.second][i];if(book[temp.to])continue;
            if (dis[temp.to] > dis[p.second] + temp.cost) {
                dis[temp.to] = dis[p.second] + temp.cost;
                P p1; p1.first = dis[temp.to]; p1.second = temp.to;
                q.push(p1);
            }
        }
    }
    return dis[1];
}
int main(void)
{
    int m,n,i,j,p,l,x,val[105],level1[105];
    cin>>m>>n;
    for(i=1;i<=n;i++){
        scanf("%d%d%d",&val[i],&level1[i],&x);
        for(j=1;j<=x;j++){
            scanf("%d%d",&p,&l);G[p].push_back(Edge{i,l});
        }
    }
    int up,down;int ans=(1<<31)-1;
    for(i=level1[1]-m;i<=level1[1];i++){
        up=i+m;down=i;memset(book,0,sizeof(book));memset(dis,0x3f,sizeof(dis));
        for(j=1;j<=n;j++){
            if(level1[j]<down||level1[j]>up){
                book[j]=1;
            }
            else{
                q.push(P(val[j],j));dis[j]=val[j];
            }
        }
        ans=min(ans,dijkstra());
    }
    cout<<ans<<endl;

    return 0;
}

C. HDU3499
题意:
有一个有向图,你要从特定的城市A飞到城市B去.给你这个图的所有边(航班)信息.但是你手上有一张卡,可以使得某一趟航班的价格减半.现在的问题是你从A到B的最小费用是多少?
首先要知道这条如果让一条原本是最短路径(假设总距离为x)上最长的边变成半价,最终求得的解不一定是最优的。因为假如现在有另外一条路径,假设该路径距离为x+1。且这条路径上只有5条边,4条长为1的边,但是1条长为x-3的边。如果我们让这条路径的x-3边变成半价是不是能得到更好的结果?
明显必须从m条边中枚举那条半价的航班.假设这条半价的航班是i->j的.那么我们必须知道从A到i的最短距离和从j到B的最短距离. 从A到i的最短距离可以通过求A的单源最短路径即可.从j(j有可能是任意点)到B的最短距离必须建立原图的反向图,然后求B到其他所有点的单源最短路径.(想想是不是)
原题输入数据很多,距离要用long long保存.
题目跟cf上某一次的题目还是比较像的。

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<map>
using namespace std;
typedef long long ll;
struct edge{
    int to;ll cost;
};
bool inque[100005];
const int N=1e5+5;
int main()
{
    int n,m,s,e,i,j,k;
    while(cin>>n>>m) {
        ll dis1[100005];memset(dis1,0x3f,sizeof(dis1));map<string,int>mp;//将名字映射为数字编号
        vector<edge>G[100005];vector<edge>G1[N];
        ll dis2[100005];memset(dis2,0x3f,sizeof(dis2));
        //for (i = 1; i <= n; i++)dis[i] = (1 << 31) - 1;
        //dis[s] = 0;
        string str1,str2;int cnt=0;
        for (i = 1; i <= m; i++) {
            cin>>str1>>str2>>j;int a,b;
            if(a=mp[str1]);
            else a=mp[str1]=++cnt;
            if(b=mp[str2]);
            else b=mp[str2]=++cnt;
            G[a].push_back(edge{b,j});G1[b].push_back(edge{a,j});
        }
        cin>>str1>>str2;
        queue<int> que;
        if(s=mp[str1]);
        else s=mp[str1]=++cnt;
        if(e=mp[str2]);
        else e=mp[str2]=++cnt;
        que.push(s);dis1[s]=0;//prevv[s]=0;
        //inque[s] = true;
        while (!que.empty()) {
            int t = que.front();
            que.pop();
            inque[t] = false;
            for (i = 0; i < G[t].size(); i++) {
                edge e = G[t][i];
                if (dis1[e.to] > dis1[t] + e.cost) {
                    dis1[e.to] = dis1[t] + e.cost;//prevv[e.to]=t;prel[e.to]=e.cost;
                    if (!inque[e.to]) {
                        que.push(e.to);
                        inque[e.to] = true;
                    }
                }
            }
        }
        que.push(e);dis2[e]=0;//prevv[s]=0;
        //inque[s] = true;
        while (!que.empty()) {
            int t = que.front();
            que.pop();
            inque[t] = false;
            for (i = 0; i < G1[t].size(); i++) {
                edge e = G1[t][i];
                if (dis2[e.to] > dis2[t] + e.cost) {
                    dis2[e.to] = dis2[t] + e.cost;//prevv[e.to]=t;prel[e.to]=e.cost;
                    if (!inque[e.to]) {
                        que.push(e.to);
                        inque[e.to] = true;
                    }
                }
            }
        }
        ll ans=(1LL<<63)-1;
        for(i=1;i<=n;i++){
            for(j=0;j<G[i].size();j++){//暴力枚举所有边
                edge e=G[i][j];
                ans=min(ans,dis1[i]+dis2[e.to]+e.cost/2);
            }
        }
        if(ans>=0x3f3f3f3f3f3f3f3f){
            cout<<-1<<endl;
        }
        else{
            cout<<ans<<endl;
        }
    }

    return 0;
}

D.HDU5521
题意:给定点数n和集合个数m,然后给你m个集合,每一个集合有si个点,集合内的点两两之间的到达时间都是ti,一个人在1,一个人在n,求两人同时出发的相遇的最短时间(或输出不可能);

由于每一个集合的点有很多,若集合两两之间连边,边数非常大,一开始这样就超时了……然后正确做法是对每一个集合再虚拟一个节点(范围是[n+1,n+m]),给每一个集合内的点连边权为ti的双向边到本集合对应虚拟节点,集合内其他点不连边,这样就可以通过虚拟的节点来到达其他地方从而减少边数(方法真是太巧妙了),然后求相遇的最短时间,显然现在无法得知到底选哪个地点作为见面地点,那就对1跑一遍单源最短路,对n跑一边单源最短路,然后统计1~n中每一个点的可能最短时间(一个人早到一个人晚到,显然用max取时间长的那个数而不是时间相加!!),然后选出1~n中的最短时间mndx,再遍历一下看哪些点的最短时间为mndx并记录输出,最后记得把最短时间除以2,因为连的边是ti,进入虚拟节点又出来会多算一次

点数为1e5,题目中说了所有集合大小之和不会超过1e6,每一个集合都有2*|Si|条边,那就是2*1e6条边因此N可设为1e5+10,M可设为2*1e6+10。

然而这还不是最优的做法,因为距离/2以后就会涉及到浮点数的问题,可能带来误差
这题是群内的点之间两两距离为ti,那不妨把Block点拆成入口和出口,然后这样连边:

<u, Block入口, 0>,<Block出口, u , 0>,<Block入口, Block出口, ti>

然后从S和T各跑一遍SPFA然后记录下Max更新答案即可,也不用像上面的解法一样除以2了,点数最差情况下一个点作为Block,应该是3e5,边数应该为2sum{Si}+m,应该是2e6+1e5

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int N=2e5+5;
struct edge{
    int to;int cost;
};
bool inque[N*2]={0};
int main()
{
    int t;cin>>t;int c=0;
    while(t--) {
        vector<edge>G[N*2];c++;cout<<"Case #"<<c<<": ";
        int n, m, i, j, k;
        cin >> n >> m ;
        int dis[N * 2],dis1[N*2];memset(dis,0x3f,sizeof(dis));memset(dis1,0x3f,sizeof(dis1));

        //for (i = 1; i <= n; i++)dis[i] = (1 << 31) - 1;
        //dis[s] = 0;
        int cnt=1;
        for (i = 1; i <= m; i++) {
            int t,s;scanf("%d%d",&t,&s);//vector<int>temp;
            for(j=1;j<=s;j++){
                scanf("%d",&k);G[k].push_back(edge{n+cnt,0});G[n+cnt+1].push_back(edge{k,0});G[n+cnt].push_back(edge{n+cnt+1,t});
            }
            cnt+=2;
        }
        queue<int> que;que.push(1);dis[1]=0;//记得初始化起点距离QAQ
        while (!que.empty()) {
            int t = que.front();
            que.pop();
            inque[t] = false;
            for (i = 0; i < G[t].size(); i++) {
                edge e = G[t][i];
                if (dis[e.to] > dis[t] + e.cost) {
                    dis[e.to] = dis[t] + e.cost;
                    if (!inque[e.to]) {
                        que.push(e.to);
                        inque[e.to] = true;
                    }
                }
            }
        }
        que.push(n);dis1[n]=0;
        while (!que.empty()) {
            int t = que.front();
            que.pop();
            inque[t] = false;
            for (i = 0; i < G[t].size(); i++) {
                edge e = G[t][i];
                if (dis1[e.to] > dis1[t] + e.cost) {
                    dis1[e.to] = dis1[t] + e.cost;
                    if (!inque[e.to]) {
                        que.push(e.to);
                        inque[e.to] = true;
                    }
                }
            }
        }
        int minn=0x3f3f3f3f;vector<int>ans;
        for(i=1;i<=n;i++){
            if(max(dis[i],dis1[i])<minn){
                minn=max(dis[i],dis1[i]);ans.clear();ans.push_back(i);
            }
            else if(max(dis[i],dis1[i])==minn)
                ans.push_back(i);
        }
        if(minn==0x3f3f3f3f){
            cout<<"Evil John"<<endl;
        }
        else{
            cout<<minn<<endl;
            for(i=0;i<ans.size();i++)
                printf("%d%c",ans[i],i==ans.size()-1?'\n':' ');
        }
    }

    return 0;
}

E.POJ1273
最大流的模板题,没啥好说的,dinic别给敲错了就行,以及n是边数,m是点数这种反人类设计

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
struct edge{
    int to,cap,rev;
};
vector<edge>G[210];
int level[205],iter[205];
void addedge(int from,int to,int cap)
{
    G[from].push_back(edge{to,cap,(int)G[to].size()});
    G[to].push_back(edge{from,0,(int)G[from].size()-1});//反向容量为0!!
}
void bfs(int s)
{
    memset(level,-1,sizeof(level));
    queue<int>que;
    level[s]=0;que.push(s);
    while(!que.empty()){
        int t=que.front();que.pop();
        for(int i=0;i<G[t].size();i++){
            edge e=G[t][i];
            if(e.cap>0&&level[e.to]<0){
                level[e.to]=level[t]+1;
                que.push(e.to);
            }
        }
    }
}
int dfs(int v,int t,int f)
{
    if(v==t)return f;
    for(int&i=iter[v];i<G[v].size();i++){//注意传引用!
        edge&e=G[v][i];
        if(e.cap>0&&level[v]<level[e.to]){
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0){
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;//不要漏了这个,很多时候可能是无法增广的
}
int maxflow(int s,int t){
    int flow=0;
    for(;;){
        bfs(s);
        if(level[t]<0)return flow;
        memset(iter,0,sizeof(iter));
        int f;
        while(f=dfs(s,t,0x7f7f7f7f))
            flow+=f;
    }
}
int main()
{
    int n,m,i,j,k;
    while(cin>>n>>m) {
        for(i=1;i<=205;i++)G[i].clear();
        for (i = 1; i <= n; i++) {
            int s, e, c;
            scanf("%d%d%d", &s, &e, &c);
            addedge(s, e, c);
        }
        cout << maxflow(1, m) << endl;
    }

    return 0;
}

F.HDU1272
很明显的并查集。//代码已经没问题了
有几点要注意的:
1.由于这里某个数字不一定会出现,所以要设一个mark来标记数字是否出现过。每次输入一对数字的关系则进行查找根结点的函数,并通过合并函数来判断两个数是否已经联通
2.如果两个数字能查找到相同的根结点就证明二者已经是相通的,再输入二者的关系就变成有多条相通的路径了。这时候答案肯定要输出“No”,如果两个数字不能查找到共同的根结点把两数字所在的集合合并,直到一组数据输入结束后,再进行判断,是否输入的关系每个数字之间都有相通的路径
3.如果每测试数据已0 0输入,也应打印出Yes! 坑爹设计无力吐槽
之前非常傻缺的把初始化的地方放错位置了结果一直在wa QAQ…

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+5;
int par[N];
int find(int x)
{
    return par[x]==x?x:par[x]=find(par[x]);//后面这一块不要漏了par[x]!!!否则就是不带路径压缩
}
bool unite(int x,int y)
{
    x=find(x),y=find(y);
    if(x==y)return false;
    par[x]=y;
    return true;
}
int main()
{
    int a,b;
    while(cin>>a>>b&&a!=-1&&b!=-1){
        if(!a&&!b){
            puts("Yes");
            continue;
        }
        for(int i=1;i<=1e5;i++)par[i]=i;
        bool isok=true;unite(a,b);bool exi[N]={0};exi[a]=exi[b]=true;
        int minn=min(a,b),maxn=max(a,b);
        while(scanf("%d%d",&a,&b)&&a&&b){
            exi[a]=exi[b]=true;minn=min(minn,min(a,b));
            maxn=max(maxn,max(a,b));
            if(!unite(a,b))
                isok=false;
        }
        //for(int i=1;i<=8;i++)cout<<par[i]<<endl;
        if(!isok){
            puts("No");continue;
        }
        int root=0;
        for(int i=minn;i<=maxn;i++){
            if(exi[i]&&find(i)==i){
                root++;
            }
        }
        if(root>1)puts("No");
        else puts("Yes");
    }

    return 0;
}```

G.POJ1422
好吧,这其实是一个最小路径覆盖的结论题…如果你不知道结论的话…GG
题意:在一个有向无环图中,从一些顶点出发,能遍历到图上所有点,要求初始选择的顶点数最少且顶点不重复遍历。
思路:
如果从某个顶点开始遍历的过程看成是路径的选择,那么问题就转化为在有向无环图中找最少的不想交的简单路径,这些路径覆盖图中的所有顶点。可见是关于最小路径覆盖的问题。
在有向无环图中,最小路径覆盖数 = 节点数 — 其对应二分图的最大匹配数。
最小路径覆盖它要求原图必须是有向无环图。然后根据原图构造二分图,方法为:将原图中的每个顶点vi一分为二,vi* 和vi**,相应的,如果原图中存在一条从vi到vj的有向边,那么就在顶点 vi* 和 vj** 之间连一条无向边,这就构造出一个路径覆盖问题所对应的二分图,在该二分图的基础上求其最大匹配数。
剩下的就是一个dinic的问题了

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
struct edge{
    int to,cap,rev;
};
vector<edge>G[410];
int level[405],iter[405];
void addedge(int from,int to,int cap)
{
    G[from].push_back(edge{to,cap,(int)G[to].size()});
    G[to].push_back(edge{from,0,(int)G[from].size()-1});//反向容量为0!!
}
void bfs(int s)
{
    memset(level,-1,sizeof(level));
    queue<int>que;
    level[s]=0;que.push(s);
    while(!que.empty()){
        int t=que.front();que.pop();
        for(int i=0;i<G[t].size();i++){
            edge e=G[t][i];
            if(e.cap>0&&level[e.to]<0){
                level[e.to]=level[t]+1;
                que.push(e.to);
            }
        }
    }
}
int dfs(int v,int t,int f)
{
    if(v==t)return f;
    for(int&i=iter[v];i<G[v].size();i++){//注意传引用!
        edge&e=G[v][i];
        if(e.cap>0&&level[v]<level[e.to]){
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0){
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;//不要漏了这个,很多时候可能是无法增广的
}
int maxflow(int s,int t){
    int flow=0;
    for(;;){
        bfs(s);
        if(level[t]<0)return flow;
        memset(iter,0,sizeof(iter));
        int f;
        while(f=dfs(s,t,0x7f7f7f7f))
            flow+=f;
    }
}
int main()
{
    int n,m,i,j;int t;cin>>t;
    while(t--){
        cin>>n>>m;
        for(i=0;i<=n*2+5;i++)G[i].clear();
        for(i=1;i<=n;i++)addedge(0,i,1),addedge(i+n,n*2+1,1);
        for(i=1;i<=m;i++){
            int s,e;scanf("%d%d",&s,&e);
            addedge(s,e+n,1);
        }
        cout<<n-maxflow(0,2*n+1)<<endl;
    }

    return 0;
}

H.51Nod - 1076
双连通分量的板子题…跑完之后对于每个查询看看是不是在一个连通分量即可…
网上抄了一发,毕竟我不会双连通分量23333(强连通都基本只会抄板子,摔

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=25000+7;

int DFN[maxn],low[maxn],cnt=0,vis[maxn];
vector <int> edge[maxn];
stack <int> st;
void dfs(int u,int pre)
{
    vis[u]=1;
    DFN[u]=low[u]=++cnt;
    st.push(u);
    int minn=DFN[u];
    if(edge[u].size()>0)
    {
        for(int i=0;i<edge[u].size();i++)
        {
            int v=edge[u][i];
            if(v==pre) continue;
            if(!vis[v])
            {
                dfs(v,u);
            }
            minn=min(low[v],minn);
        }
    }
    low[u]=minn;
    if(low[u]==DFN[u])
    {
        while(1)
        {
            int x=st.top();
            st.pop();
            low[x]=DFN[u];
            if(x==u) break;
        }
    }
}
int main()
{
    int n,m,i,j,k,x,y;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    for(i=1;i<=n;i++)
    {
        if(!vis[i]) dfs(i,0);
    }
    int q;
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d%d",&x,&y);
        if(low[x]==low[y]) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

I.BZOJ 1003
SPFA+DP的问题,当然我是不会的2333
做法:
令cost[i][j]为从第i天到第j天都用同一条航线的最小花费,这个做n^2遍spfa即可(如果某个点的不可用区间跟i,j有交集,那么就标记 为不可用),得到cost数组后,设dp[i]表示前i天的最小总成本,那么考虑上一次是在第j天后变换航线(j=0,1,…,i-1,第一天选择航线也被看作是一次改变航线,算出dp[n]后再减掉多加的成本k即可),那么有以下转移方程dp[i]=min(dp[j]+cost[j+1][i]+k),j=0,1,…,i-1,dp[n]-k即为最小总成本。注意开longlong
代码暂时有bug,待更新

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
struct edge{
    int to,cost;
};
const int M=25;
vector<edge>G[M];
bool inque[M];
int dis[M];
int spfa(int s,int t)
{
    memset(dis,0x3f,sizeof(dis));dis[s]=0;int i,j;
    queue<int>que;que.push(s);inque[s]=true;
    while(!que.empty()){
        int t=que.front();que.pop();inque[t]=false;
        for(i=0;i<G[t].size();i++){
            edge e=G[t][i];if(inque[e.to])continue;
            if(dis[e.to]>dis[t]+e.cost){
                dis[e.to]=dis[t]+e.cost;
                if(!inque[e.to]){
                    que.push(e.to);inque[e.to]=true;
                }
            }
        }
    }
    return dis[t];
}
int main()
{
    int n,m,s,i,j,k,e,seg[25][105]={0};
    cin>>n>>m>>k>>e;
    //for(i=1;i<=n;i++)dis[i]=(1<<31)-1;
    //dis[s]=0;
    for(i=1;i<=e;i++){
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        G[a].push_back(edge{b,c});G[b].push_back(edge{a,c});
    }
    int d;cin>>d;
    while(d--){
        int p,a,b;cin>>p>>a>>b;
        for(i=a;i<=b;i++)seg[p][i]=1;
    }
    int cost[105][105]={0};
    for(i=1;i<=n;i++)
        for(j=i;j<=n;j++){
        memset(inque,0,sizeof(inque));
        for(int k=2;k<m;k++){
            for(int l=i;l<=j;l++){
                if(seg[k][l]) {
                    inque[k] = true;
                    break;
                }
            }
        }
        s=spfa(1,m);
        if(s==0x3f3f3f3f)
            cost[i][j]=0x3f3f3f3f;
        else cost[i][j]=s*(j-i+1);
    }
    int f[105];memset(f,0x3f,sizeof(f));f[0]=0;
    for(i=1;i<=n;i++){
        for(j=0;j<i;j++)
            f[i]=min(f[i],f[j]+cost[j+1][i]+k);
    }
    //for(i=1;i<=n;i++)cout<<f[i]<<endl;
    cout<<f[n]-k<<endl;

    return 0;
}

J.留个坑

两相交错并联BuckBoost变换器仿真模型(Simulink仿真实现) 内容概要:本文档系统整合了电力电子与新能源领域的Simulink仿真资源,聚焦于两相交错并联Buck-Boost变换器的双闭环PWM控制建模与仿真,同时涵盖多种典型拓扑结构,包括交错并联Boost、PFC功率因数校正、LLC谐振变换器、双向CLLC、DAB变换器、VIENNA整流器等。资源体系完整,包含仿真模型、设计报告、计算书、PPT说明文档及Matlab/Python代码,覆盖从基础建模到高级控制策略(如软开关技术、谐波抑制、状态估计、双闭环控制)的全流程。此外,还拓展至状态估计(卡尔曼滤波、粒子滤波)、智能优化算法、机器学习、信号处理、路径规划等多个交叉学科方向,构建了一个面向科研与工程应用的综合性技术平台。; 适合人群:电气工程、自动化、电力电子、新能源科学与工程等专业的硕士博士研究生、高校科研人员,以及从事新能源发电、智能电网、电动汽车、电力传动等领域技术研发的工程师。; 使用场景及目标:①开展电力电子变换器(如Buck-Boost、LLC、DAB、PFC等)的建模、控制与仿真研究;②支撑课程设计、学位论文、科研项目中的系统仿真与算法验证;③学习并复现高水平期刊(如EI)提出的先进控制策略,如基于KKT条件的最优控制、扩展移相调制、恒压恒流双环竞争控制等;④结合智能算法(如粒子群、秃鹰算法)进行微电网调度、储能配置、路径规划等多目标优化问题的研究与快速原型开发。; 阅读建议:建议依据提供的资源目录循序渐进地查阅资料,优先选取与自身研究方向高度契合的内容进行深入学习;应结合仿真模型与配套文档动手实践,调试参数并分析结果,充分利用百度网盘与公众号渠道获取完整资源,提升科研工作的系统性、规范性与创新性。 立即下载

相关推荐

【基于Zernike矩的良性和恶性肿块的分类】应用于乳腺癌诊断中的快速相反权重学习规则(Matlab代码实现)

内容概要:本文详细介绍了基于Plecs软件构建的全桥LLC谐振变换器仿真模型,重点阐述了其在软开关技术条件下的建模方法与仿真分析过程。该模型能够精确模拟LLC谐振变换器在不同运行工况下的动态响应特性,涵盖开环与闭环控制策略的设计与实现,适用于研究变换器的效率优化、谐振参数匹配、系统稳定性及软开关性能等问题。相较于Simulink等传统仿真工具,Plecs在高频电力电子系统仿真中展现出更高的仿真速度与数值精度,尤其适合用于复杂电力电子拓扑的快速原型验证与优化设计。; 适合人群:具备扎实电力电子技术基础和仿真经验,从事高频功率变换器设计、新能源电源开发、电力电子系统研究的研发工程师及高校研究生。; 使用场景及目标:①深入理解全桥LLC谐振变换器的工作原理与软开关实现机制;②掌握在Plecs环境中搭建高精度、高效率电力电子系统仿真模型的方法;③开展变换器控制策略(如变频控制、闭环稳压)的仿真验证与参数优化;④为科研课题、学位论文或工业项目提供可靠的仿真平台与技术支持。; 阅读建议:建议结合相关电力电子教材与LLC变换器设计指南,深入掌握谐振参数计算与系统稳定性分析方法,并通过反复调试仿真模型,观察关键波形(如原边电流零点切换、副边整流波形),以全面理解软开关过程的物理本质与控制实现细节。

UVA302 UVALive5517 John's trip【欧拉回路+DFS】

Little Johnny has got a new car. He decided to drive around the town to visit his friends. Johnny wanted to visit all his friends, but there was many of them. In each street he had one friend. He star...

海岛Blog 700

QT/C++实现健壮HTTP POST客户端:从基础到异常处理与性能优化

HTTP协议作为客户端与服务器通信的基石,其POST方法在数据提交、API交互等场景中扮演着核心角色。其工作原理基于请求-响应模型,通过封装TCP连接与协议细节,为应用层提供了简洁的数据传输接口。在C++桌面与嵌入式开发中,直接使用底层Socket实现HTTP不仅复杂且易出错,而利用框架进行高级封装能显著提升开发效率与代码健壮性。QT框架的`QNetworkAccessManager`等组件正是为此设计,它通过信号槽机制提供异步网络编程模型,有效管理连接与协议解析。一个健壮的HTTP客户端需要妥善处理网络波

weixin_29176179的博客 384

2018 Spring Training 字符串合集

A.HDU3374 题目其实很简单,就是求给定串的最大最小表示法,然后求出现的次数的话,就把原串复制一遍接在串尾,然后跑一遍kmp求出现次数即可。 #include&amp;amp;amp;amp;lt;cstdio&amp;amp;amp;amp;gt; #include&amp;amp;amp;amp;lt;iostream&amp;amp;amp;amp;gt; #include&amp;amp;amp;amp;lt;string&amp;amp

HumveeA6的博客 379

ADS仿真设计平行定向耦合器学习笔记

ADS仿真设计平行定向耦合器

qq_36521926的博客 1万+

STM32H743的ADC还能这么玩?定时器触发+DMA搬运,构建低CPU占用的数据流

本文深入探讨了STM32H743微控制器中ADC的高效使用方法,通过定时器触发和DMA搬运技术实现低CPU占用的数据流采集。详细解析了硬件架构、CubeMX配置步骤及高级优化技巧,包括双缓冲技术和多ADC同步采样,适用于电机控制、音频采集等高性能应用场景。

weixin_30698527的博客 647

(模板)二分图最大匹配,最大流算法

转换为最大流做即可。注意加边的技巧。 代码如下: #include&lt;cstdio&gt; #include&lt;iostream&gt; #include&lt;algorithm&gt; #include&lt;cstring&gt; #include&lt;vector&gt; #include&lt;queue&gt; using namespace std; struc...

HumveeA6的博客 1787

QT的温湿度显示系统

大家好,这里是石侃侃的博客,欢迎前来讨论这篇文章介绍的是DHT11在2440上的基于Qt5.6的应用基于单片机系统的温湿度监测系统构成框图如图2-1所示。图2-1 系统构成框图该系统采用单片机s3c2440作为了本设计的核心元件。利用LCD作为了显示器件,利用触摸屏作为用户界面输入设备,第一行显示当前实时的温度,湿度,第二行依次显示历史时刻最高的温度值,最高的湿度值。第三行是一个文本框,记录了程...

zxpcus的博客 1万+

(模板) Dijkstra算法(priority_queue优化)

写法1,利用struct存当前最近点的信息: #include&lt;cstdio&gt; #include&lt;iostream&gt; #include&lt;vector&gt; #include&lt;algorithm&gt; #include&lt;cstring&gt; #include&lt;queue&gt; using namespace std; struct edg...

HumveeA6的博客 1477

Qt实战:用QCustomPlot实现毫秒级时间轴数据动态刷新(附完整代码)

本文深入探讨了在Qt框架下,如何利用QCustomPlot库高效实现毫秒级时间轴数据的动态刷新与实时可视化。针对工业物联网等高频数据场景,文章提供了从原理剖析、核心代码实现到性能优化的完整实战指南,包括滑动窗口管理、双定时器策略及坐标轴精确配置,帮助开发者构建稳定、流畅的专业级监控界面。

qsc90123456的博客 758

倍福PLC--PERSISTENT断电保持数据和BOOT中各文件对应的解析

将D:\TC3程序\TwinCAT Project146\TwinCAT RT(x86)\Plc 文件夹的中三个替换文件复制到:G:\TwinCAT\3.1\Boot\Plc完成替换,如下图。(2) 找到程序所存的路径,编程电脑的D:\TC3程序\TwinCAT Project146路径下,并选择对应系统平台TwinCAT RT(x86)(3) 控制器断电,拔出内存卡,使用读卡器,在编程电脑中打开:(本次测试读卡器为G盘)(5) 开机完成后,TwinCAT自动运行,当前闪灯频率为50ms。

weixin_41883890的博客 2340

有上下界的网络流 做法总结

无源汇可行流 建图方法 将有上下界的网络流图转化成普通的网络流图 首先建立附加源点ss和附加汇点tt 对于原图中的边x-&amp;amp;gt;y,若限制为[b,c],那么连边x-&amp;amp;gt;y,流量为c-b 对于原图中的某一个点i,记d(i)为流入这个点的所有边的下界和减去流出这个点的所有边的下界和 若d(i)&amp;amp;gt;0,那么连边ss-&amp;amp;gt;i,流量为d(i) 若d(i)&amp;amp;lt;0,那么连

HumveeA6的博客 687

CGAL AlphaShape算法(自适应Alpha值,二维版本)

CGAL AlphaShape算法(自适应Alpha值,二维版本)

dayuhaitang1的博客 2322

SGU 194/LOJ 115(无源汇可行流模板)

题意: 给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质。 并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li。 例如: 46(4个点,6个pipe) 12 1 3 (1-&amp;gt;2上界为3,下界为1...

HumveeA6的博客 656

goahead(嵌入式Web服务器)之文件传输篇

goahead文件上传原理: 使用html form即表单提交文件上传请求,web服务器核心处理接收客户端Post过来的文件数据(注意post的是二进制数据),最后,web服务器把接收到文件数据以二进制格式写到服务器本端存储系统。 goahead文件上传步骤: 1、创建upload.html文件,内容如下: <html> <head> <meta charset="utf-8"/> <title>Upload</title> </head&g

weixin_40732273的博客 3495

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

洛谷P4009 汽车加油行驶问题

虽然写着网络流,但是似乎spfa跑最短路更好做一些。 需要注意的是如果某个地方有油站,那么是一定要加满油才能往后走的。 然后距离的记录以及边与平时的spfa有一些不同。 每个点如果有油,可以往4个方向转移。 别的就没有什么了。 #include&lt;cstdio&gt; #include&lt;iostream&gt; #include&lt;algorithm&gt; #incl...

HumveeA6的博客 600

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Aizu 2200/AOJ2200

题目大意:快递到了:你是某个岛国(ACM-ICPC Japan)上的一个苦逼程序员,你有一个当邮递员的好基友利腾桑遇到麻烦了:全岛有一些镇子通过水路和旱路相连,走水路必须要用船,在X处下船了船就停在X处。而且岛上只有一条船,下次想走水路还是得回到X处才行;两个镇子之间可能有两条以上的水路或旱路;邮递员必须按照清单上的镇子顺序送快递(镇子可能重复,并且对于重复的镇子不允许一次性处理,比如ABCB的话...

HumveeA6的博客 555

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Aizu 2249

以dis为权值,求最短路,再开一个pre数组,pre[i]表示从首都到i城的最短路中,i城的上一座城市到i城的cost。最后将求出的最短路所有pre加起来就好了(为什么这样,画图可以考虑考虑,大概还是有道理的) 因为你始终还是要求首先满足最短路这个条件,之所以可以删去一些路,就是因为一些路有重复。如果用最小生成树的话这题似乎并不好弄。 同时,i城到首都的最短路可能有多条,这时pre里面存的是多...

HumveeA6的博客 492

LOJ 117 有源汇有上下界最小流(模板)

建图方法 将有上下界的网络流图转化成普通的网络流图 首先建立附加源点ss和附加汇点tt 对于原图中的边x-&amp;amp;amp;gt;y,若限制为[b,c],那么连边x-&amp;amp;amp;gt;y,流量为c-b 对于原图中的某一个点i,记d(i)为流入这个点的所有边的下界和减去流出这个点的所有边的下界和 若d(i)&amp;amp;amp;gt;0,那么连边ss-&amp;amp;amp;gt;i,流量为d(i) 若d(i)&amp;amp;

HumveeA6的博客 484

LOJ 116 有源汇有上下界最大流(模板)

建图方法 将有上下界的网络流图转化成普通的网络流图 首先建立附加源点ss和附加汇点tt 对于原图中的边x-&gt;y,若限制为[b,c],那么连边x-&gt;y,流量为c-b 对于原图中的某一个点i,记d(i)为流入这个点的所有边的下界和减去流出这个点的所有边的下界和 若d(i)&gt;0,那么连边ss-&gt;i,流量为d(i) 若d(i)&lt;0,那么连边i-&gt;tt,流量...

HumveeA6的博客 461

洛谷P2766最长不下降子序列问题(网络流24题)

【问题分析】 第一问时LIS,动态规划求解,第二问和第三问用网络最大流解决。 【建模方法】 首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K。 1、把序列每位i拆成两个点i.a和i.b,从i.a到i.b连接一条容量为1的有向边。 2、建立附加源S和汇T,如果序列第i位有F[i]=K,从S到i.a连接一条容量为1的有向边。 3、如果F[i]=1,从...

HumveeA6的博客 453

(模板)割点(割顶)tarjan类算法

题目的大致描述:给出一个n个点,m条边的无向图,求图的割点。 个人说不清楚,放几个图吧 代码如下: vector&lt;int&gt;G[100005]; int sccindex=0,low[100005],dfn[100005]; bool vis[100005],gd[100005]; int ans=0; void tarjan(int v,int fa)//其实这题...

HumveeA6的博客 447

洛谷P1197

如果从正面去做,每干一个点跑一次tarjan之类的,肯定会tle;所以不妨反(倒着)着来,把摧毁星球变成添加星球,这样就是每次跑并查集了。至于如何快速确定联通块的数量嘛,并查集每连一条边就是减少了一个联通快,不过要注意的是初始的时候联通快的数量是n-k!!!!此外还是有不少小坑需要留意的。 #include&lt;cstdio&gt; #include&lt;iostream&gt; #incl...

HumveeA6的博客 433

最小路径覆盖(模板)

对于一个给定的有向无环图(DAG),求其最小路径覆盖。题目可参见洛谷P2764。 【问题分析】 有向无环图最小路径覆盖,可以转化成二分图最大匹配问题,从而用最大流解决。 【建模方法】 构造二分图,把原图每个顶点i拆分成二分图X,Y集合中的两个顶点Xi和Yi。对于原图中存在的每条边(i,j),在二分图中连接边(Xi,Yj)。然后把二分图最大匹配模型转化为网络流模型,求网络最大流。 最小路径...

HumveeA6的博客 432

CF 472B Mystical Mosaic

刚开始的时候考虑过各种暴力,不过似乎都太复杂了以至于写着写着就出错了或者写不下去了。这题其实有非常简便的做法。对于矩阵中的每一列,如果在该列的某一行处是”#”,那么在选中该列的同时该行也是一定要同时选中的。那么,对于任意的两列i,j,如果他们需要选中的行一样,OK,没问题,这两列可以在同一次选择中被选中。但是,如果i,j需要选择的行不一样,那么他们肯定就不能在同一次中选择了,否则的话这两列肯定会多...

HumveeA6的博客 432

(模板)Floyd算法(多源最短路)

最最最需要注意的就是因为每次是拿一个点出来考虑能否把别的路变短,所以k一定是最外层循环。以及要记得初始化为无穷大或无穷小。 可以通过检查是否有dis[i][i]&lt;0来判定是否有负环存在 int dis[105][105]; memset(dis,0x7f,sizeof(dis)); for(i=1;i&lt;=n;i++) for(j=1;j&lt;=n;...

HumveeA6的博客 425
上一篇: Educational Codeforces Round 38 (Rated for Div. 2)
下一篇: Codeforces Round #485 (Div. 2)
HumveeA6
博客等级 码龄17年 12粉丝 175原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值