当前位置: 首页 > wzjs >正文

辉县市工程建设网站建设百度网盘官方网站

辉县市工程建设网站建设,百度网盘官方网站,免费自制app软件手机,商业网站在规划与设计时应着重考虑哪些因素基础前置知识: 有向图: 欧拉路径: 定义:在有向图中,从一个顶点出发,经过每条边恰好一次,并且遍历所有顶点的路径称为有向图的欧拉路径。 特征:有向图存在欧拉路径,当…

基础前置知识:

有向图:

欧拉路径:

定义:在有向图中,从一个顶点出发,经过每条边恰好一次,并且遍历所有顶点的路径称为有向图的欧拉路径。

特征:有向图存在欧拉路径,当且仅当该图是连通的,且除了两个顶点外其余顶点的入度等于出度。这两个特殊顶点中,一个顶点的入度比出度大 1(终点),另一个顶点的出度比入度大 1(起点)。如果全部点的入度和出度数都是相等的也可以。

欧拉回路:

定义:在有向图中,从一个顶点出发,经过每条边恰好一次,最后回到起始顶点的路径称为有向图的欧拉回路。

特征:有向图存在欧拉回路,当且仅当该图是连通的,且所有顶点的入度等于出度。

无向图

欧拉路径:

定义:在无向图中,从一个顶点出发,经过每条边恰好一次,并且遍历所有顶点的路径称为无向图的欧拉路径。

特征:无向图存在欧拉路径,当且仅当该图是连通的,且图中奇度顶点(度数为奇数的顶点)的个数为 0 或 2。若奇度顶点个数为 0,则可以从任意顶点出发;若奇度顶点个数为 2,则必须从其中一个奇度顶点出发,到另一个奇度顶点结束。

欧拉回路:

定义:在无向图中,从一个顶点出发,经过每条边恰好一次,最后回到起始顶点的路径称为无向图的欧拉回路。

特征:无向图存在欧拉回路,当且仅当该图是连通的,且所有顶点的度数均为偶数

4个板子题

有向图的欧拉路径:

题目描述

求有向图字典序最小的欧拉路径。

输入格式

第一行两个整数 n,m 表示有向图的点数和边数。

接下来 m 行每行两个整数 u,v 表示存在一条 u→v 的有向边。

输出格式

如果不存在欧拉路径,输出一行 No。

否则输出一行 m+1 个数字,表示字典序最小的欧拉路径。

代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 100005;

// 存储图的邻接表

vector<int> g[N];

// 记录每个节点的入度

int in[N];

// 记录每个节点的出度

int out[N];

// 存储欧拉路径

int s[N];

int top=0;

// 深度优先搜索函数,用于寻找欧拉路径

void dfs(int u) {

    // 遍历从节点 u 出发的所有边

    while (!g[u].empty()) {

        // 取出字典序最小的邻接节点

        int v = g[u].back();

        g[u].pop_back();

        // 递归调用 dfs 函数继续搜索

        dfs(v);

    }

    // 将节点 u 加入欧拉路径

    s[++top]=u;

}

int main() {

    int n, m;

    // 读取图的点数 n 和边数 m

    cin >> n >> m;

    // 读取每条边的信息,并更新入度和出度

    for (int i = 0; i < m; i++) {

        int u, v;

        cin >> u >> v;

        // 将边 (u, v) 加入邻接表

        g[u].push_back(v);

        // 节点 v 的入度加 1

        in[v]++;

        // 节点 u 的出度加 1

        out[u]++;

    }

    // 对每个节点的邻接表进行排序,以保证按字典序遍历

    for (int i = 1; i <= n; i++) {

        sort(g[i].begin(), g[i].end(), greater<int>());

    }

    

    // 寻找可能的起始节点

    int start = 1;

    int cnt = 0;

    bool flag = true;

    for (int i = 1; i <= n; i++) {

        if (out[i] - in[i] == 1) {

            // 出度比入度大 1 的节点作为起始节点

            start = i;

            cnt++;

        } else if (out[i] - in[i] == -1) {

            cnt++;

        } else if (out[i] != in[i]) {

            // 若存在节点入度和出度差值不为 0、1 或 -1,则不存在欧拉路径

            flag = false;

            break;

        }

    }

    // 欧拉路径要求要么所有节点入度等于出度(欧拉回路),要么有两个节点入度和出度差值为 1 和 -1

    if (cnt != 0 && cnt != 2) {

        flag = false;

    }

    if (!flag) {

        // 若不存在欧拉路径,输出 No

        cout << "No" << endl;

    } else {

        // 从起始节点开始深度优先搜索

        dfs(start);

        // 输出欧拉路径

        while (top) {

            cout << s[top--];

            if (top) {

                cout << " ";

            }

        }

        cout << endl;

    }

    return 0;

}

无向图的欧拉路径:

重点是度数的奇偶性

同样的上面的题,但是改成无向图

题目描述

求无向图字典序最小的欧拉路径。

输入格式

第一行两个整数 n,m 表示有向图的点数和边数。

接下来 m 行每行两个整数 u,v 表示存在一条 u→v 的有向边。

输出格式

如果不存在欧拉路径,输出一行 No。

否则输出一行 m+1 个数字,表示字典序最小的欧拉路径。

代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 100005;

// 存储图的邻接表

vector<int> g[N];

// 记录每个节点的度数

int degree[N];

// 存储欧拉路径

int s[N];int top = 0;

// 深度优先搜索函数,用于寻找欧拉路径

void dfs(int u) {

    // 遍历从节点 u 出发的所有边

    while (!g[u].empty()) {

        // 取出字典序最小的邻接节点

        int v = g[u].back();

        // 从 u 的邻接表中删除 v,同时也从 v 的邻接表中删除 u(无向图)

        g[u].pop_back();

        it = find(g[v].begin(), g[v].end(), u);

        if (it != g[v].end()) {

            g[v].erase(it);

        }

        // 递归调用 dfs 函数继续搜索

        dfs(v);

    }

    // 将节点 u 加入欧拉路径

s[++top] = u;

}

int main() {

    int n, m;

    // 读取图的点数 n 和边数 m

    cin >> n >> m;

    // 读取每条边的信息,并更新节点度数

    for (int i = 0; i < m; i++) {

        int u, v;

        cin >> u >> v;

        // 将边 (u, v) 加入邻接表(无向图,双向添加)

        g[u].push_back(v);

        g[v].push_back(u);

        // 节点 u 和 v 的度数都加 1

        degree[u]++;

        degree[v]++;

    }

    // 对每个节点的邻接表进行排序,以保证按字典序遍历

    for (int i = 1; i <= n; i++) {

        sort(g[i].begin(), g[i].end(), greater<int>());

    }

    // 寻找可能的起始节点

    int start = 1;

    int oddDegreeCount = 0;

    bool flag = true;

    for (int i = 1; i <= n; i++) {

        if (degree[i] % 2 == 1) {

            // 度数为奇数的节点

            oddDegreeCount++;

            start = i;

        }

        if (degree[i] % 2 == 1 && oddDegreeCount > 2) {

            // 若奇数度数节点超过 2 个,则不存在欧拉路径

            flag = false;

            break;

        }

    }

    if (oddDegreeCount != 0 && oddDegreeCount != 2) {

        // 奇数度数节点不为 0 或 2 时,不存在欧拉路径

        flag = false;

    }

    if (!flag) {

        // 若不存在欧拉路径,输出 No

        cout << "No" << endl;

    } else {

        // 从起始节点开始深度优先搜索

        dfs(start);

        // 输出欧拉路径

        while (top) {

            cout << s[top--];

            if (top) {

                cout << " ";

            }

        }

        cout << endl;

    }

return 0;

}

有向图的欧拉回路:

题目描述

求有向图字典序最小的欧拉回路。

输入格式

第一行两个整数 n,m 表示有向图的点数和边数。

接下来 m 行每行两个整数 u,v 表示存在一条 u→v 的有向边。

输出格式

如果不存在欧拉路径,输出一行 No。

否则输出一行 m+1 个数字,表示字典序最小的欧拉路径。

代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 100005;

// 存储图的邻接表

vector<int> g[N];

// 记录每个节点的入度

int in[N];

// 记录每个节点的出度

int out[N];

// 存储欧拉回路

int s[N];int top = 0;

// 深度优先搜索函数,用于寻找欧拉回路

void dfs(int u) {

    // 遍历从节点 u 出发的所有边

    while (!g[u].empty()) {

        // 取出字典序最小的邻接节点

        int v = g[u].back();

        g[u].pop_back();

        // 递归调用 dfs 函数继续搜索

        dfs(v);

    }

    // 将节点 u 加入欧拉回路

    s[++top] = u;}

int main() {

    int n, m;

    // 读取图的点数 n 和边数 m

    cin >> n >> m;

    // 读取每条边的信息,并更新入度和出度

    for (int i = 0; i < m; i++) {

        int u, v;

        cin >> u >> v;

        // 将边 (u, v) 加入邻接表

        g[u].push_back(v);

        // 节点 v 的入度加 1

        in[v]++;

        // 节点 u 的出度加 1

        out[u]++;

    }

    // 对每个节点的邻接表进行排序,以保证按字典序遍历

    for (int i = 1; i <= n; i++) {

        sort(g[i].begin(), g[i].end(), greater<int>());

    }

    // 检查是否存在欧拉回路  和上面唯一不一样的地方

    bool flag = true;

    for (int i = 1; i <= n; i++) {

        if (in[i] != out[i]) {

            // 若存在节点入度和出度不相等,则不存在欧拉回路

            flag = false;

            break;

        }

    }

    if (!flag) {

        // 若不存在欧拉回路,输出 No

        cout << "No" << endl;

    } else {

        // 从节点 1 开始深度优先搜索

        dfs(1);

        // 输出欧拉回路

        while (top) {

            cout << s[top--];

            if (top) {

                cout << " ";

            }

        }

        cout << endl;

    }

return 0;

}

无向图的欧拉回路

题目描述

求无向图字典序最小的欧拉回路。

输入格式

第一行两个整数 n,m 表示有向图的点数和边数。

接下来 m 行每行两个整数 u,v 表示存在一条 u→v 的有向边。

输出格式

如果不存在欧拉路径,输出一行 No。

否则输出一行 m+1 个数字,表示字典序最小的欧拉路径。

代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 100005;

// 存储图的邻接表

vector<int> g[N];// 记录每个节点的度数int degree[N];// 存储欧拉回路int s[N];int top = 0;

// 深度优先搜索函数,用于寻找欧拉回路void dfs(int u) {

    // 遍历从节点 u 出发的所有边

    while (!g[u].empty()) {

        // 取出字典序最小的邻接节点

        int v = g[u].back();

        // 从 u 的邻接表中删除 v,同时也从 v 的邻接表中删除 u(无向图)

        g[u].pop_back();

        auto it = find(g[v].begin(), g[v].end(), u);

        if (it != g[v].end()) {

            g[v].erase(it);

        }

        // 递归调用 dfs 函数继续搜索

        dfs(v);

    }

    // 将节点 u 加入欧拉回路

    s[++top] = u;}

int main() {

    int n, m;

    // 读取图的点数 n 和边数 m

    cin >> n >> m;

    // 读取每条边的信息,并更新节点度数

    for (int i = 0; i < m; i++) {

        int u, v;

        cin >> u >> v;

        // 将边 (u, v) 加入邻接表(无向图,双向添加)

        g[u].push_back(v);

        g[v].push_back(u);

        // 节点 u 和 v 的度数都加 1

        degree[u]++;

        degree[v]++;

    }

    // 对每个节点的邻接表进行排序,以保证按字典序遍历

    for (int i = 1; i <= n; i++) {

        sort(g[i].begin(), g[i].end(), greater<int>());

    }

    // 检查是否存在欧拉回路  改变的地方

    bool flag = true;

    for (int i = 1; i <= n; i++) {

        if (degree[i] % 2 != 0) {

            // 若存在节点度数为奇数,则不存在欧拉回路

            flag = false;

            break;

        }

    }

    if (!flag) {

        // 若不存在欧拉回路,输出 No

        cout << "No" << endl;

    } else {

        // 从节点 1 开始深度优先搜索

        dfs(1);

        // 输出欧拉回路

        while (top) {

            cout << s[top--];

            if (top) {

                cout << " ";

            }

        }

        cout << endl;

    }

return 0;

}

练习题:

USACO3.3 骑马修栅栏 

题目背景

Farmer John 每年有很多栅栏要修理。他总是骑着马穿过每一个栅栏并修复它破损的地方。

题目描述

John 是一个与其他农民一样懒的人。他讨厌骑马,因此从来不两次经过一个栅栏。

John 的农场上一共有 m 个栅栏,每一个栅栏连接两个顶点,顶点用 1 到 500 标号(虽然有的农场并没有那么多个顶点)。一个顶点上至少连接 1 个栅栏,没有上限。两顶点间可能有多个栅栏。所有栅栏都是连通的(也就是你可以从任意一个栅栏到达另外的所有栅栏)。John 能从任何一个顶点(即两个栅栏的交点)开始骑马,在任意一个顶点结束。

你需要求出输出骑马的路径(用路上依次经过的顶点号码表示),使每个栅栏都恰好被经过一次。如果存在多组可行的解,按照如下方式进行输出:如果把输出的路径看成是一个 500 进制的数,那么当存在多组解的情况下,输出 500 进制表示法中最小的一个 (也就是输出第一位较小的,如果还有多组解,输出第二位较小的,以此类推)。

输入数据保证至少有一个解。

输入格式

第一行一个整数 m,表示栅栏的数目。

从第二行到第 (m+1) 行,每行两个整数 u,v,表示有一条栅栏连接 u,v 两个点。

输出格式

共 (m+1) 行,每行一个整数,依次表示路径经过的顶点号。注意数据可能有多组解,但是只有上面题目要求的那一组解是认为正确的。

数据保证至少有一组可行解。

代码


#include <bits/stdc++.h>

using namespace std;

const int N=2000;//说好的1-500,开到了2000才过最后一个

vector<int> g[N];

int s[N];

int top=0;

int degree[N]={0};

int m;

//逆序最小==>在dfs的循环中,大的先想办法让他们后遍历,后入栈

//dfs在回溯后,当前点u才入栈,所以尽可能让小的点当做start

//欧拉路径 ==> 0/2个奇数点

bool cmp(int u,int v){

    return u>v;

}

void dfs(int u){

    while(!g[u].empty()){

        int v=g[u].back();

        g[u].pop_back();

        auto it=find(g[v].begin(),g[v].end(),u);

        if(it!=g[v].end()){

            g[v].erase(it);

        }

        dfs(v);

    }

    s[++top]=u;

}

int main(){

    scanf("%d",&m);

    int n=0;

    int minn=0x3f3f3f3f;

    for(int i=0;i<m;i++){

        int u,v;

        scanf("%d%d",&u,&v);

        n=max(n,max(u,v));

        minn=min(minn,min(u,v));

        g[u].push_back(v);

        g[v].push_back(u);

        degree[u]++;degree[v]++;

    }

    int start=minn;

    while(!degree[start])start++;//把起点初始化到有边的地方

    for(int i=1;i<=n;i++){

        sort(g[i].begin(),g[i].end(),cmp);

    }

    //保证了有解没必要去判断,直接找起点

    for(int i=1;i<=n;i++){

        if(degree[i]&1){

            start=i;

            break;

        }

    }

    

    dfs(start);

    

    while(top){

        printf("%d",s[top--]);

        if(top)printf("\n");

    }

    

}

POJ 1386-play on words

Description

Some of the secret doors contain a very interesting word puzzle. The team of archaeologists has to solve it to open that doors. Because there is no other way to open the doors, the puzzle is very important for us.

There is a large number of magnetic plates on every door. Every plate has one word written on it. The plates must be arranged into a sequence in such a way that every word begins with the same letter as the previous word ends. For example, the word ``acm'' can be followed by the word ``motorola''. Your task is to write a computer program that will read the list of words and determine whether it is possible to arrange all of the plates in a sequence (according to the given rule) and consequently to open the door.

Input

The input consists of T test cases. The number of them (T) is given on the first line of the input file. Each test case begins with a line containing a single integer number Nthat indicates the number of plates (1 <= N <= 100000). Then exactly Nlines follow, each containing a single word. Each word contains at least two and at most 1000 lowercase characters, that means only letters 'a' through 'z' will appear in the word. The same word may appear several times in the list.

Output

Your program has to determine whether it is possible to arrange all the plates in a sequence such that the first letter of each word is equal to the last letter of the previous word. All the plates from the list must be used, each exactly once. The words mentioned several times must be used that number of times.
If there exists such an ordering of plates, your program should print the sentence "Ordering is possible.". Otherwise, output the sentence "The door cannot be opened.".

题意翻译

输入n(n≤100000)个单词,是否可以把所有这些单词排成一个序列,使得每个单词的第一个字母可上一个单词的最后一个字母相同(例如acm,malform,mouse)。每个单词最多包含1000个小写字母。输入中可以有重复的单词。

代码:

#include <bits/stdc++.h>

using namespace std;

const int M=100010;

const int N=30;

int t;

int n,m;

//有向图的欧拉路径问题,需要记录入度和出度

int in[N];

int out[N];

//26个字母有可能有些不在图中,我们去标记下

int use[N];

//a-z看成26个点

//首字母xxxxxx尾字母

//一个单词看做是一个首字母连接到为字母的边

int p[N];

int find(int x){

    if(x!=p[x])p[x]=find(p[x]);

    return p[x];

}

void merge(int x,int y){

    int px=find(x),py=find(y);

    if(px==py)return ;

    p[px]=py;

}

int main(){

    scanf("%d",&t);

    char tmp[1001];

    while(t--){

        scanf("%d",&m);

        memset(in,0,sizeof in);

        memset(out,0,sizeof out);

        memset(use,0,sizeof use);

        memset(p,0,sizeof p);

        //连通性判断,直接使用并查集吧

        for(int i=0;i<26;i++)p[i]=i;

        while(m--){

            scanf("%s",tmp);

            int len=strlen(tmp);

            int u=tmp[0]-'a';

            int v=tmp[len-1]-'a';

            out[u]++;

            in[v]++;

            use[u]=use[v]=1;

            merge(u,v);

        }

        //判断欧拉路径

        //有向图的欧拉路径是入度和出度都相等or2个不等,一个出度大1的是start,另外一个是end

        int oddcnt=0;

        bool flag=true;

        int start=0;

        int end=0;

        for(int i=0;i<26;i++){

            if(!use[i])continue;

            if(in[i]!=out[i]){

                if(out[i]-in[i]==1)

                    start++;

                else if(out[i]-in[i]==-1)

                    end++;

                else

                    flag=false;

                oddcnt++;

            }

        }

        if(!((start==0&&end==0)||start==1&&end==1))flag=0;

        if(oddcnt!=0&&oddcnt!=2)flag=false;

        int lca=-1;

        for(int i=0;i<26;i++){

            if(!use[i])continue;

            int par=find(i);

            if(lca==-1)lca=par;

            else if(par!=lca){

                flag=false;

                break;

            }

        }

        if(!flag)printf("The door cannot be opened.");

        else printf("Ordering is possible.");

        if(t)printf("\n");

    }

}

http://www.dtcms.com/wzjs/283234.html

相关文章:

  • 网站新闻页设计百度广告怎么投放多少钱
  • 做网站的公司哪家靠谱30个免费货源网站
  • 郑州网站建设郑州网络推广阿里指数数据分析平台
  • 自己网站建设多少钱磁力最好用的搜索引擎
  • 做网站需要用什么开发软件网站建设详细方案模板
  • 营销型集团网站建设seo博客网址
  • 网站客服软件哪个好哪些网站可以发广告
  • 网站如何开启gzip压缩百度推广没有一点效果
  • 网站安全设计网址大全名称
  • 医药网站建设需要注意点深圳开发公司网站建设
  • 郑州营销型网站制作策划厦门网站建设平台
  • 昆明网站seo外包奶茶推广软文200字
  • 游戏策划是做什么的seo优化排名易下拉软件
  • 网站建设类行业资讯360收录批量查询
  • 网站开发于制作总结制作网站大概多少钱
  • 网站开发公司宣传语企业邮箱网页版
  • 建设网站方法app代理推广合作
  • Java做新闻网站网店推广实训系统
  • 建设网站要先备案才能操作呢怎样做企业宣传推广
  • 医院seo是什么南昌seo排名扣费
  • 怎样做货源网站实事新闻热点
  • 新网站2个月没有收录长沙seo排名优化公司
  • 网站建设图片上传bing搜索国内版
  • .net开发的网站有哪些百seo排名优化
  • 衢州网站建设广州seo优化排名推广
  • vi毕业设计代做网站seo是什么意思知乎
  • 在网站后台挂马网站seo分析报告
  • 娄底网站建设企业白山seo
  • 网站后台管理系统怎么开发河源市seo点击排名软件价格
  • 建设网站的意义 作用是什么产品线上营销推广方案